繁体   English   中英

MySQL计算列中子字符串出现次数

[英]MySQL Count number of substring occurrences in column

使用MySQL,我试图计算每一行中一个子串的出现次数。

在下面的示例表中,字符串“art”在“条款”列中出现三次,因此它的计数为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

我会写这个,首先编写一个只返回我们想要返回的术语列表的查询。 例如:

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

然后将其包装在parens中并将其用作内联视图...

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的匹配

查询可以被修改,以符合terms只出现在其他的开始 terms

跟进

使用示例数据,返回:

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(REPLACE( w.terms ,'\\','\\\\'),'_','\_'),'%','\%')
                 ^^^^^^^^         ^^^^^^^^^^^^^

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM