MySQL - select 来自一列的不同值,其中值以逗号分隔

MySQL - select distinct values from a column where values are separated by comma

要从 table1 和 column1 中获取不同值的列表就像这样做一样简单:

SELECT distinct(column1) 
FROM table1

但是,我(不幸地)继承了一个数据库,其中 column1 包含以逗号分隔的值

column1
--------
row 1: name1,name2
row 2: name2,name3
row 3: name4,name1,name3

我需要从 column1 中获取不同值的列表,所以它看起来像这样:

column1
--------
name1
name2
name3
name4

有什么想法吗?

你不能。您的数据库不遵守设计规范化数据库的首要原则:- 原子性。它说在一列中存储一个且只有一个属性,但你有这么多。您需要从您的应用程序中检索整个列值、拆分和 de-dupe 它们。 SQL 无法为您完成此操作。

您在这里真正需要做的是拥有一个单独的 NAMES table 并在过滤相关行后在名称列上应用 DISTINCT。

你必须把它们分开。如果列中最多有三个名称,则一种方法是:

select substring_index(column1, ',', 1) as name
from t
union -- on purpose to remove duplicates
select substring_index(substring_index(column1, ',', 2), ',', -1) as name
from t
where name like '%,%'
union -- on purpose to remove duplicates
select substring_index(substring_index(column1, ',', 3), ',', -1) as name
from t
where name like '%,%,%';

通用方法使用递归查询(仅在 MySQL 8.0 中可用):

with recursive 
    data as (select concat(column1, ',') rest from mytable),
    words as (
        select substring(rest, 1, locate(',', rest) - 1) word, substring(rest, locate(',', rest) + 1) rest
        from data
        union all
        select substring(rest, 1, locate(',', rest) - 1) word, substring(rest, locate(',', rest) + 1) rest
        from words
        where locate(',', rest) > 0
)
select distinct word from words order by word

Demo on DB Fiddle

示例数据:

| column1           |
| :---------------- |
| name1,name2       |
| name2,name3       |
| name4,name1,name3 |

结果:

| word  |
| :---- |
| name1 |
| name2 |
| name3 |
| name4 |