考虑以下MySQL函数以计算字符串的单词数:
DELIMITER $$
CREATE DEFINER=`localhost` FUNCTION `wordcount`(`str` TEXT) RETURNS int(11)
NO SQL
DETERMINISTIC
SQL SECURITY INVOKER
BEGIN
DECLARE wordCnt, idx, maxIdx INT DEFAULT 0;
DECLARE currChar, prevChar BOOL DEFAULT 0;
SET maxIdx=char_length(str);
WHILE idx < maxIdx DO
SET currChar=SUBSTRING(str, idx, 1) RLIKE '[[:alnum:]]';
IF NOT prevChar AND currChar THEN
SET wordCnt=wordCnt+1;
END IF;
SET prevChar=currChar;
SET idx=idx+1;
END WHILE;
RETURN wordCnt;
END$$
DELIMITER ;
尽管此功能似乎可以正常运行,但不幸的是,它比PHP str_word_count()
慢得多。例如,对于6万个字符的文本,MySQL函数大约需要15秒,而PHP函数几乎是瞬时的。
有什么想法可以改善它吗?
答案 0 :(得分:2)
如果您不需要确切的答案,则可以使用毫无疑问会在其他地方找到的空格计数技术来获得大致的答案-基本上假设单词数是空格数加1。因为您经常遇到双空格在句子之间,可以先使用REPLACE将两个空格替换为一个,以获得更好的价值。如果您已经在使用mySQL 8,则可以使用REGEX_REPLACE将任意长度的空格转换为单个空格,这显然会更好。这是一个示例(不使用mySQL 8):
select length(replace(str, ' ', ' ')) - length(replace(str, ' ', '')) + 1 from ... where ...
它并不完美,但是对于大多数纯文本而言,它都还不错。而且不需要15秒。
编辑:在评论中回复您的问题。如果您需要摆脱控制字符等,我可以在5.6上提出的最好选择是多个替换。例如:
select length(replace(replace(str, '\n', ' '), ' ', ' ')) - length(replace(replace(str, ' ', ''), '\n', '')) + 1 from ... where ...
那之后变得更难看了。如果需要更精确,我将做您在PHP中所做的任何事情。如果您要根据数据库中的字数查找目标,请将其用作“松散过滤器”进行选择,然后使用PHP进行精确过滤。例如,如果您要查找500到600个单词之间的内容,请使用它来查找450到650个单词,然后对选定的行进行实际计数,以确定它们是否真正符合条件。