MySQL计算列

时间:2017-03-08 22:05:36

标签: mysql

使用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

1 个答案:

答案 0 :(得分:3)

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

 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的子字符串,子字符串匹配出现在术语的开头。此查询还将查找术语不在开头的匹配项。

e.g。 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 ,'\\','\\\\'),'_','\_'),'%','\%')
                 ^^^^^^^^         ^^^^^^^^^^^^^