在一个VARCHAR字段中计算一个字符串出现的次数?

238
我有一个如下所示的表格:
TITLE DESCRIPTION
test1 value blah blah value
test2 value test
test3 test test test
test4 valuevaluevaluevaluevalue
我想知道如何返回每个DESCRIPTION中特定字符串出现的次数。例如,如果我要计算“value”出现的次数,则SQL语句将返回以下结果:
TITLE DESCRIPTION COUNT
test1 value blah blah value 2
test2 value test 1
test3 test test test 0
test4 valuevaluevaluevaluevalue 5
有没有什么办法可以实现这一点?我不想使用PHP,只想用MySQL。

6
以下回复可以帮助您完成此操作。但是,如果您使用多字节字符,请不要忘记使用CHAR_LENGTH()而不是LENGTH() - inhan
这个线程也在这里得到了回答。 - Delickate
嗨,我该如何使用SQL Server查询来完成这个任务? - aintno12u
LENGTH([field]) - LENGTH(REPLACE([field], '[char_to_find]', ''))长度([字段]) - 长度(替换([字段], '[要查找的字符]', '')) - Phoenix
8个回答

453

这应该可以解决问题:

SELECT 
    title,
    description,    
    ROUND (   
        (
            LENGTH(description)
            - LENGTH( REPLACE ( description, "value", "") ) 
        ) / LENGTH("value")        
    ) AS count    
FROM <table> 

69
这个解决方案很棒,正好符合我的需求!但请注意,LENGTH() 不支持多字节,并且可能会导致奇怪的错误。请改用 CHAR_LENGTH() :) - nico gawenda
2
在计算相同的字节数/字符数时,使用LENGTH()CHAR_LENGTH()没有区别。@nicogawenda - MohaMad
3
“undevalue” 中包含“value”,因此应该计算在内。如果您只想计算完整的单词,也许需要搜索“ value ”,或者更好的方法是使用正则表达式来进行搜索。 - PhoneixS
3
请注意,在搜索包含大写字母的单词的文本(例如德语,其中所有名词都用大写字母写)时,您会遇到错误的计数。 REPLACE仅替换精确匹配的单词。为了考虑所有单词,您需要将上面的替换更改为:LENGTH( REPLACE ( LOWER(description), "value", "") ) 并使用PHP的 strtolower() 使“value”始终小写。 PS: 以上解决方案帮助我构建了自己的小型搜索引擎,并通过文本中的单词数量对结果进行加权。谢谢! - Avatar
4
这里的ROUND是不必要的。假设有一个长度为x,包含'value'出现次数为n的字符串description,则LENGTH(description) - LENGTH(REPLACE(description, "value", ""))总是会得到n*length("value"),将其除以value的长度总会留下一个整数n。无需四舍五入。 - Nibhrit
显示剩余6条评论

53

这里是@yannis解决方案的更加简单和有效的变体:

SELECT 
    title,
    description,    
    CHAR_LENGTH(description) - CHAR_LENGTH( REPLACE ( description, 'value', '1234') ) 
        AS `count`    
FROM <table> 

我的做法是将"value"字符串替换为一个比其短1个字符的字符串(在本例中为"1234")。这样就不需要进行除法和四舍五入操作来得到整数值。

通用版本(适用于任何针字符串):

SET @needle = 'value';
SELECT 
    description,    
    CHAR_LENGTH(description) - CHAR_LENGTH(REPLACE(description, @needle, SPACE(LENGTH(@needle)-1))) 
        AS `count`    
FROM <table> 

2
虽然我通常更喜欢明显的实现方式,即使它们看起来不太优雅,但我赞同这个想法。 - not2savvy

26

试试这个:

 select TITLE,
        (length(DESCRIPTION )-length(replace(DESCRIPTION ,'value','')))/5 as COUNT 
  FROM <table> 

SQL Fiddle示例


3
长度不是二进制安全的,请使用char_length()函数。 - luky

15
在SQL SERVER中,这就是答案。
Declare @t table(TITLE VARCHAR(100), DESCRIPTION VARCHAR(100))

INSERT INTO @t SELECT 'test1', 'value blah blah value' 
INSERT INTO @t SELECT 'test2','value test' 
INSERT INTO @t SELECT 'test3','test test test' 
INSERT INTO @t SELECT 'test4','valuevaluevaluevaluevalue' 


SELECT TITLE,DESCRIPTION,Count = (LEN(DESCRIPTION) - LEN(REPLACE(DESCRIPTION, 'value', '')))/LEN('value') 

FROM @t

结果

TITLE   DESCRIPTION               Count
test1   value blah blah value        2
test2   value test                   1
test3   test test test               0
test4   valuevaluevaluevaluevalue    5

我没有安装MySQL,但是通过谷歌搜索发现LEN的等效函数是LENGTH,而REPLACE则相同。

因此,在MySQL中等效的查询应该是:

SELECT TITLE,DESCRIPTION, (LENGTH(DESCRIPTION) - LENGTH(REPLACE(DESCRIPTION, 'value', '')))/LENGTH('value') AS Count
FROM <yourTable>

请告诉我这个在 MySql 中是否有效。

6
这里有一个可以实现此功能的函数。
CREATE FUNCTION count_str(haystack TEXT, needle VARCHAR(32))
  RETURNS INTEGER DETERMINISTIC
  BEGIN
    RETURN ROUND((CHAR_LENGTH(haystack) - CHAR_LENGTH(REPLACE(haystack, needle, ""))) / CHAR_LENGTH(needle));
  END;

3
这是使用空格技巧的mysql函数(已在mysql 5.0 + 5.5上测试):
CREATE FUNCTION count_str( haystack TEXT,  needle VARCHAR(32))
  RETURNS INTEGER DETERMINISTIC
  RETURN LENGTH(haystack) - LENGTH( REPLACE ( haystack, needle, space(char_length(needle)-1)) );

utf-8 字符计数错误 count_str('BÆS', 'Æ') = 2,上面的 char_length 版本是正确的。 - luky

1
SELECT 
id,
jsondata,    
ROUND (   
    (
        LENGTH(jsondata)
        - LENGTH( REPLACE ( jsondata, "sonal", "") ) 
    ) / LENGTH("sonal")        
)
+
ROUND (   
    (
        LENGTH(jsondata)
        - LENGTH( REPLACE ( jsondata, "khunt", "") ) 
    ) / LENGTH("khunt")        
)
AS count1    FROM test ORDER BY count1 DESC LIMIT 0, 2

谢谢Yannis,你的解决方案对我很有用,现在我要分享同样的解决方案,可以按照顺序和限制来处理多个关键词。


1
在大多数情况下,这些功能分别是LENGTH和REPLACE(SQL Server用户将使用内置函数LEN而不是LENGTH):
例如,在字符串“10,CLARK,MANAGER”中计算逗号的数量。
select (length('10,CLARK,MANAGER')-
        length(replace('10,CLARK,MANAGER',',','')))/length(',')
as cnt from t1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接