如何在表

时间:2017-07-22 11:54:29

标签: mysql database count group-by word-count

我有一个带varchar(255)字段的表。我想从此表中获取一组行中每个单词的出现次数。 我的表:

col1    col2    col3
123    A,B,C    Some Value
345      A      Some Value
567      B      Some Value
876    B,C      Some Value
890    C,A      Some Value
231    A,C      Some Value
456     B       Some Value
678     C       Some Value

我想要输出

Alpha   Count
A       4
B       4
C       5

1 个答案:

答案 0 :(得分:0)

我确信您知道将逗号分隔值放入单行的单个列中几乎绝对不好的数据库设计。 (如果您对此不确定,请阅读规范化。)

但几乎绝望并非没有希望。您可以从逗号分隔的字符串中提取单个项目,如下所示。以下表达式从逗号分隔列表中检索第四项。如果列表没有四个项目,则会检索一个空字符串。

SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',4),',',-1) w FROM tbl

你可以read about SUBSTRING_INDEX() here。内部调用从col2检索每个直到第四个逗号。外部调用从末尾开始向后工作,并检索到第一个逗号的所有内容。看哪,你的话。卡在col2末尾的额外逗号可以防止col2的值少于四个逗号的错误。

接下来,您需要反复使用这些表达式来获取每行的第一,第二,第三,第四......单词。您可以将它们放入UNION ALL查询中,如下所示。

SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',1),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',2),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',3),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',4),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',5),',',-1) w FROM tbl

注意每个表达式如何依次检索第一个,第二个,第三个等单词。

接下来,我们需要将所有这些包装在外部查询中以清理它并摆脱零长度的“单词”。看起来像这样:(http://sqlfiddle.com/#!9/1cd35/4/0

SELECT col1, TRIM(w) w
FROM (
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',1),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',2),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',3),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',4),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',5),',',-1) w FROM tbl
) words
WHERE w <> ''

最后,我们将对所有这些进行汇总以进行计数。 (http://sqlfiddle.com/#!9/1cd35/6/0

SELECT COUNT(*) wordcount, TRIM(w) w
FROM (
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',1),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',2),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',3),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',4),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',5),',',-1) w FROM tbl
) words
WHERE w <> ''
GROUP BY TRIM(w)
ORDER BY COUNT(*) DESC

请注意,您可以使用此类查询在名为words的表格中创建数据的规范化版本,如下所示:

CREATE TABLE words
SELECT col1, TRIM(w) word
FROM (
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',1),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',2),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',3),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',4),',',-1) w FROM tbl
UNION ALL
SELECT col1, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(col2,',,,,,'),',',5),',',-1) w FROM tbl
) words
WHERE TRIM(w) <> ''

然后你可以做

   SELECT COUNT(*) wordcount, word 
    FROM words 
   GROUP BY word
   ORDER BY COUNT(*) DESC, word

简单的方法。

你可能已经注意到检索你的单词的查询是重复的,在UNION ALL中有很多单独的SELECT。该列中每个可能数量的逗号分隔值都有一个。是啊。 几乎没有希望有时会有点讨厌处理。如果您有一些col2值,其中包含一万个逗号,则需要使用宿主程序以规范化形式重写表。