2011-03-17 18 views
1

编辑:可以看出,我决定去与mySQL的“匹配”。这就是说,如果有人知道一个干净的方法在SELECT语句中做我想做的事情,我将不胜感激这些信息(为了知识和所有这些知识)mySQL:搜索多行的字符串,并根据字符串的频率排序结果

我目前正在开发本地搜索引擎一个我正在设计的网站,因此我用来确定文章相关性的一种方式是搜索词在文章中出现的次数。因此,我正在寻找一个SQL查询,它允许我拉取包含搜索词的行(文章),并根据搜索词在每行(文章)中出现的次数来排序它们。

换句话说,我需要这样的事情...

SELECT article_id FROM articles_table WHERE article_content LIKE '%Search Terms%' ORDER BY COUNT(number of times string appears in article_content); 

所以,如果用户搜索“帝国”和拉升以下三篇文章...

  1. 帝国是帝国。
  2. 帝国是一个棒球位置的名称。
  3. 帝国帝国帝国。

这将排序他们既然这么..

  1. 帝国帝国帝国
  2. 帝国是帝国
  3. 帝国在棒球运动中的位置的名称。

我在PHP中工作,虽然理想情况下我想只用一个SQL查询来执行此操作,但如果这不可能,我向PHP解决方案开放。

任何和所有的帮助,非常感谢。

+0

你有没有尝试过匹配?你发现了什么结果? – Pentium10 2011-03-17 17:23:37

回答

4

你应该真的考虑一个Full Text搜索解决方案。无论是使用MyISAM表和MySQL native full text search,或者你可以去外方式使用类似Sphinx fulltext搜索或Lucene

+0

你比我的好:-) – Ben 2011-03-17 17:26:18

+0

@Ben,谢谢,但你也+1,因为你更快:) – JohnP 2011-03-17 17:27:12

+0

感谢你和本......我可能会去那。我已经为此做了一些工作,并且我想为了自己的缘故完成它(知识就是力量等等),但是暂时与预先建立的搜索一​​起进行无疑是最好的想法。在这种情况下,我希望提供一些易于实施但相当有效的搜索工具的建议。我正在研究你现在提到的那些......但其他人的意见总是有帮助=) – Wipqozn 2011-03-17 17:34:41

2

不是严格的答案,但你有没有考虑过像Lucene这样的全文搜索引擎?我的意思是,不是建立你自己的,而是不那么好。

3

我完全与其他的答案一致。 Theorically你可以做这样的事情

select (char_length('The Empire The Empire The Empire') - 
     char_length(replace(lower('The Empire The Empire The Empire'),lower('empire'),'')))/char_length('empire') as occurrences 

找到一个搜索词出现的频率在您的字符串,但是这是一个可怕的方法

+0

虽然很聪明! – Ben 2011-03-17 17:31:15

+0

是的,我遇到类似的东西......但是就像你说的那样,这是一个相当可怕的方法,当然肯定还有其他方法(除了使用其他人提出的搜索解决方案,我打算与之合作现在) – Wipqozn 2011-03-17 17:39:07

1

这里是不使用全文检索

使用测试聪明
DROP TABLE IF EXISTS articles_table;
CREATE TABLE articles_table

ARTICLE_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
article_content TEXT
)ENGINE = MyISAM数据;
INSERT INTO articles_table(article_content)VALUES
( '帝国是帝国'),
( '帝国是在棒球的位置的名称。'),
( '帝国帝国帝国' );
SELECT * FROM articles_table;

lwdba @ localhost(DB test):: SELECT * FROM articles_table;
+ ------------ + ---------------------------------- ----------------- +
| article_id | article_content |
+ ------------ + ---------------------------------- ----------------- +
| 1 |帝国是帝国|
| 2 |帝国是棒球界的名字。 |
| 3 |帝国帝国帝国|
+ ------------ + ---------------------------------- ----------------- +
3行中集合(0.00秒)

SELECT article_content,
REPLACE(article_content, '帝国', '') newstring,
LENGTH(article_content)origlen,
LENGTH(REPLACE(article_content, '帝国', ''))newlen,
FLOOR((LENGTH(article_content) - LENGTH(REPLACE(article_content, '帝国', ')))/(LENGTH('The Empire')))得分
FROM articles_table;

+ --------------------------------------------- ------ + ----------------------------------------- + - -------- + -------- + ------- +
| article_content | newstring | origlen | newlen |分数| + ------------------------------------------------ --- + ----------------------------------------- + ---- ----- + -------- + ------- +
|帝国是帝国|是| 24 | 4 | 2 |
|帝国是棒球界的名字。 |是棒球中的位置的名称。 | 49 | 39 | 1 |
|帝国帝国帝国| | 32 | 2 | 3 |
+ ----------------------------------------------- ---- + ---------------------------------------- + ---- ----- + -------- + ------- +

得分是原始字符串的删除次数。

增广查询只显示原始文本和得分:

SELECT * FROM(SELECT article_content,FLOOR((长度(article_content) - 长(REPLACE(article_content, '帝国', '') ))/(LENGTH('The Empire')))得分FROM articles_table)AA ORDER BY得分DESC;

下面是最终产品

lwdba @本地(DB测试):: SELECT * FROM(SELECT article_content,FLOOR((长度(article_content) - 长(REPLACE(article_content, '帝国', '' ))/(LENGTH('T he Empire')))score FROM articles_table)AA ORDER BY score DESC;
+ ----------------------------------------------- ---- + ------- +
| article_content |分数|
+ ----------------------------------------------- ---- + ------- +
|帝国帝国帝国| 3 |
|帝国是帝国| 2 |
|帝国是棒球界的名字。 | 1 |
+ ----------------------------------------------- ---- + ------- +
设置3行(0.06秒)

只需在查询的两个地方插入任何所需的字符串!

试试吧!

更新:哦,我试了!

+0

是的,这个方法与nick rulez发布的方法类似。 一个聪明的方法是肯定的,但如果有一个更清洁的方式,而不使用MATCH或这样的技巧是很好的。无论如何,谢谢你的答案=) – Wipqozn 2011-03-17 18:08:08