6

我正在为我的网站创建搜索功能,该功能可以从数据库中查找相关结果。我正在寻找一种计算单词出现次数的方法,但我需要确保单词的两侧都有单词边界(所以当我想要“rip”时,我不会以“triple”结尾)。

有没有人有任何想法?


人们误解了我的问题:

如何计算单行中此类事件的数量?

4

9 回答 9

2

这不是关系数据库非常擅长的事情,除非您可以使用全文索引,并且您已经声明不能,因为您使用的是 InnoDB。我建议选择您的相关行并在您的应用程序代码中进行字数统计。

于 2010-02-16T17:07:36.497 回答
1

你可以试试这种变态的方式:

SELECT 
(LENGTH(field) - LENGTH(REPLACE(field, 'word', ''))) / LENGTH('word') AS `count`
ORDER BY `count` DESC
  • 这个查询可能很慢
  • 看起来很丑
  • REPLACE() 区分大小写
于 2010-02-16T17:03:00.067 回答
1

您可以REPLACE()通过使用LOWER().

它草率,但在我看来,这个查询运行得非常快。

为了加快速度,我在一个选择中检索结果集,我在“外部”查询中声明为派生表。由于此时 mysql 已经有了结果,因此 replace 方法的工作速度非常快。

我创建了一个类似于下面的查询来在多个表和多个列中搜索多个术语。我获得了一个“相关性”数字,该数字等于搜索的所有列中所有找到的搜索词的所有出现次数的总和

SELECT DISTINCT ( 
((length(x.ent_title) - length(replace(LOWER(x.ent_title),LOWER('there'),''))) / length('there')) 
+ ((length(x.ent_content) - length(replace(LOWER(x.ent_content),LOWER('there'),''))) / length('there'))
 + ((length(x.ent_title) - length(replace(LOWER(x.ent_title),LOWER('another'),''))) / length('another')) 
+ ((length(x.ent_content) - length(replace(LOWER(x.ent_content),LOWER('another'),''))) / length('another')) 
) as relevance, 
x.ent_type, 
x.ent_id, 
x.this_id as anchor,
page.page_name
FROM ( 
(SELECT 
'Foo' as ent_type, 
sp.sp_id as ent_id, 
sp.page_id as this_id, 
sp.title as ent_title, 
sp.content as ent_content,
sp.page_id as page_id
FROM sp
WHERE (sp.title LIKE '%there%' OR sp.content LIKE '%there%' OR sp.title LIKE '%another%' OR sp.content LIKE '%another%' ) AND (sp_content.title NOT LIKE '%goes%' AND sp_content.content NOT LIKE '%goes%')
) UNION (
  [search a different table here.....]
)
) as x
JOIN page ON page.page_id = x.page_id 
WHERE page.rstatus = 'ACTIVE'
ORDER BY relevance DESC, ent_title;

希望这可以帮助某人

——西克雷斯特出局

于 2010-08-17T23:49:06.383 回答
1

创建一个像这样的用户定义函数并在您的查询中使用它

DELIMITER $$

CREATE FUNCTION `getCount`(myStr VARCHAR(1000), myword VARCHAR(100))
    RETURNS INT
    BEGIN
    DECLARE cnt INT DEFAULT 0;
    DECLARE result INT DEFAULT 1;

    WHILE (result > 0) DO
    SET result = INSTR(myStr, myword);
    IF(result > 0) THEN 
        SET cnt = cnt + 1;
        SET myStr = SUBSTRING(myStr, result + LENGTH(myword));
    END IF;
    END WHILE;
    RETURN cnt;    

    END$$

DELIMITER ;

希望它有助于 参考这个

于 2013-07-26T19:26:38.757 回答
0

像这样的东西应该工作:

select count(*) from table where fieldname REGEXP '[[:<:]]word[[:>:]]';

血淋淋的细节在 MySQL 手册的 11.4.2 节中。

于 2008-12-28T05:12:10.513 回答
0

像 LIKE 或 REGEXP 这样的东西不会扩展(除非它是最左边的前缀匹配)。

考虑改为使用全文索引来执行您想要做的事情。

select count(*) from yourtable where match(title, body) against ('some_word');
于 2008-12-28T15:27:50.677 回答
0

我使用了下面链接中描述的技术。MySQL的方法用途lengthreplace功能。

关键字相关性

于 2008-12-29T19:45:17.643 回答
0

如果您想要搜索,我建议使用 Sphinx 或 Lucene 之类的东西,我发现 Sphinx(作为独立的全文索引器)更容易设置和运行。它运行速度很快,并且生成索引的速度非常快。即使您使用的是 MyISAM,我也建议您使用它,它比 MyISAM 的全文索引功能强大得多。

它还可以(在某种程度上)与 MySQL 集成。

于 2010-12-04T23:46:51.570 回答
-3

这取决于您使用的 DBMS,有些允许编写可以执行此操作的 UDF。

于 2010-08-17T23:55:53.340 回答