2017-03-08 67 views
1

使用MySQL,我试图计算每列中子字符串出现次数。MySQL计算列中子字符串出现次数

在下面的示例表,字符串“艺术”出现在条款柱三次,所以它必须3.

示例表的计数:

TERMS 
art 
artistic 
painting 
elephant 
art deco 
paint 
paintings 

所需的输出:

TERMS  COUNT 
art  3 
artistic 1 
painting 2 
elephant 1 
art deco 1 
paint  2 
paintings 1 

编辑:

作为一个起点,我知道:

SELECT terms, COUNT(*) 
FROM table 
GROUP BY terms 

将输出每个完整术语字符串的出现次数。对于子字符串匹配,我认为这可能涉及子查询。

试过以下,但每计数1

SELECT terms, ROUND((CHAR_LENGTH(terms) - CHAR_LENGTH(REPLACE(terms, terms, "")))/CHAR_LENGTH(terms)) AS count 
FROM table 
GROUP BY terms 
+0

请与我们分享您的试验。 –

+0

你的替换函数用它自己替换每一行的术语;在我的答案中看看建议1和2。 – MohaMad

回答

2

我会先写一个查询,只是返回我们要返回术语列表写这篇文章。例如:

SELECT t.terms 
    FROM `table` t 
    GROUP BY t.terms 

然后包裹在括号并用它作为内嵌视图...

SELECT w.terms 
    FROM (SELECT t.terms 
      FROM `table` t 
      GROUP BY t.terms 
     ) w 
ORDER BY w.terms 

这样,我们可以做一个连接操作来寻找匹配的行,并获得了计数。假设terms不包含下划线(_)或百分比(%)字符的保证,我们可以使用LIKE比较。

鉴于我们列表中的每个术语至少会出现一次,我们可以使用内部联接。在更一般的情况下,我们可能希望返回零计数,我们将使用外连接。

SELECT w.terms 
    , COUNT(1) AS `COUNT` 
    FROM (SELECT t.terms 
      FROM `table` t 
      GROUP BY t.terms 
     ) w 
    JOIN `table` c 
    ON c.terms LIKE CONCAT('%', w.terms ,'%') 
GROUP BY w.terms 
ORDER BY w.terms 

LIKE比较,百分号是通配符匹配任何字符(零个,一个或更多)。

如果有可能terms确实包含下划线或百分号字符,我们可以将它们转义,以便它们不被LIKE比较视为通配符。像这样的表达应该做的伎俩:

REPLACE(REPLACE(w.terms ,'_','\_'),'%','\%') 

所以我们不得不这样的查询:

SELECT w.terms 
    , COUNT(1) AS `COUNT` 
    FROM (SELECT t.terms 
      FROM `table` t 
      GROUP BY t.terms 
     ) w 
    JOIN `table` c 
    ON c.terms LIKE CONCAT('%',REPLACE(REPLACE(w.terms ,'_','\_'),'%','\%'),'%') 
GROUP BY w.terms 
ORDER BY w.terms 

还有其他的查询模式,将返回指定的结果。这只是一种方法的演示。


注意:在这个问题的例子,每一个terms那是另一个terms一子,子字符串匹配出现在开始术语。此查询还会查找匹配项不在开头的位置。

例如dartboard将被视为匹配art

的查询可以修改,以符合仅出现在开始的其他termsterms

随访

随着数据。例如,返回:

terms  COUNT  matched_terms 
--------- -------- ------------------------- 
art    3 art,art deco,artistic 
art deco   1 art deco 
artistic   1 artistic 
elephant   1 elephant 
paint    3 paint,painting,paintings 
painting   2 painting,paintings 
paintings   1 paintings 

除了COUNT(1)骨料,我还包括在选择列表中的另一种表达。这不是必需的,但它确实提供了关于哪些术语被认为是匹配的一些附加信息。

GROUP_CONCAT(DISTINCT c.terms ORDER BY c.terms) AS `matched_terms` 

注意:如果有一种可能性,即terms包含反斜杠字符,就可以逃避这些字符以及使用替换另一个

REPLACE(REPLACE(REPLACE(w.terms ,'\\','\\\\'),'_','\_'),'%','\%') 
       ^^^^^^^^   ^^^^^^^^^^^^^ 
+1

非常好的答案!但是在'ORDER BY'之前你不需要'GROUP BY w.term'吗? –

+1

@MichaelK:是的。我们确实需要一个GROUP BY。 * DOH!*(回答编辑包含更正。) – spencer7593

+0

当我学习新事物时喜欢它..优雅的解决方案 –

相关问题