MySQL分组按逗号分隔列表唯一

时间:2020-07-02 03:56:58

标签: mysql

textfield中有逗号分隔的列表值

ID  | textfield
1   |  english,russian,german
2   |  german,french
3   |  english
4   |  null

我正在尝试计算文本字段中的语言数量。默认语言是“英语”,因此如果为null,则为“英语”。正确的语言数量是4(英语,俄语,德语,法语)。

这是我的查询以尝试执行此操作:

SELECT SUM((length(`textfield`) - length(replace(`textfield`, ',', '')) + 1)) as my
FROM yourtable;

我得到的结果是6,我不知道如何对语言进行分组。

这里是小提琴 http://sqlfiddle.com/#!9/0e532/1

期望的结果是4。如何解决?

2 个答案:

答案 0 :(得分:1)

对于5.6版(如小提琴)

SELECT COUNT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(languages.textfield, ',', numbers.num), ',', -1)) languages_count
FROM (SELECT COALESCE(textfield, 'english') textfield
      FROM yourtable) languages
JOIN (SELECT 1 num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) numbers
    ON numbers.num <= LENGTH(languages.textfield) - LENGTH(REPLACE(languages.textfield, ',', '')) + 1;

fiddle

对于8.x版(如评论中所述)

SELECT COUNT(DISTINCT jsontable.value) languages_count
FROM yourtable
CROSS JOIN JSON_TABLE( CONCAT('["', REPLACE(COALESCE(textfield, 'english'), ',', '","'), '"]'),
                       "$[*]" COLUMNS( value VARCHAR(254) PATH "$" )
                     ) AS jsontable;

fiddle

答案 1 :(得分:1)

确定错误来源

您的查询正在做的是计算每一行中有多少种语言,并将它们全部加在一起。您的查询不考虑重复项。由于英语在表格中显示两次,因此它被计数两次(德语也被计数),因此在您的示例中为六次。另外,另一个问题是您当前的代码将null视为真正意义,即没有值。 例如,如果您的数据库是

ID | textfield
---|----------
1  | null

您还会得到不正确的结果(更多信息请参见下文)。

解决方案

这使您得到逗号分隔的语言结果,没有重复。

SELECT
    GROUP_CONCAT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(textfield, ',', n.digit+1), ',', -1)) textfield
  FROM
    yourtable
    INNER JOIN
    (SELECT 0 digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6) n
    ON LENGTH(REPLACE(textfield, ',', '')) <= LENGTH(textfield)-n.digit;

此查询可以用作subquery,以指示您在问题提示中尝试执行的操作。换句话说,您无需提供length('textfield') ...,而是可以通过此查询提供结果列名称

不能为英文

不应在数据库级别IMHO上实现此逻辑。如果您想继续考虑null条目为英文,那很好。缺点是我之前为您提供的示例。当您有一个查询可解决数据库中的所有语言的查询时,如果英语不是明确所说的语言,而是一个null值,则该查询将不会“计数” '英文(无效)。但是,每次发现语言数量时,您都不能只加1,因为英语可能已经很明确了。

建议: