从 MySQL table 中检索不同的 concat 值

Retrieve Distinct concat values from MySQL table

我有一个 SQL table 广告

id       name       cat
11       abc        ab
12       acb        ab, bc
13       abb        bcd
14       abcd       ad
15       acbd       de
16       abbd       ad

在使用 DISTINCT 函数时,我得到这样的输出

查询:

SELECT DISTINCT cat FROM advert;

输出:

ab
ab, bc
bcd
ad
de

我需要对这样的输出查询进行哪些更改

ab
bc
bcd
ad
de

我认为你应该改变你的 table 结构,让它变成这样。

tblName

id    | name
11       abc        
12       acb       
13       abb       
14       abcd      
15       acbd       
16       abbd

tblCat

id          | name_id |  cat
some ids*       11        ab
                12        ab
                12        bc
                13        bcd
                14        ad
                15        de
                16        ad

通过这种方式,您可以轻松查询和管理您 table 中的数据。

您应该修复您的数据结构,这样您就不会在列中存储以逗号分隔的列表。这是在关系数据库中存储数据的错误方法。 . .正如您从回答这个简单问题的问题中看到的那样。你想要的是一个路口 table.

有时,我们会被其他人糟糕的设计困住。你说只有两个or值,那么你可以这样做:

select cat
from ((select substring_index(cat, ', ', 1) as cat
       from advert
      ) union all
      (select substring_index(substring_index(cat, ', ', 2), ', ', -1) as cat
       from advert
       where cat like '%, %'
      ) union all
      (select substring_index(substring_index(cat, ', ', 3), ', ', -1) as cat
       from advert
       where cat like '%, %, %'
      )
     ) c
group by cat;

首先...我将创建一个语句,将所有行变成一个巨大的逗号分隔列表。

DECLARE @tmp VarChar(max)
SET @tmp = ''
SELECT @tmp = @tmp + ColumnA + ',' FROM TableA

然后使用这篇 SO 文章中描述的 table 值 udf 拆分将大量字符串转回 table 并带有不同的子句以确保它是唯一的。

SELECT DISTINCT * FROM dbo.Split(',', @tmp)

完整代码示例:

if object_id('dbo.Split') is not null
    drop function dbo.Split
go
CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(512))
RETURNS table
AS
RETURN (
    WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @s)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT pn,
      SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
    FROM Pieces
  )
go
declare @t table (colA varchar(max))
insert @t select '111, 223'
union all select '333'
union all select '444'
union all select '777,999';

select  ltrim(rtrim(s.s)) as colC
from    @t t
cross apply
        dbo.split(',', t.colA) s
select distinct trim(substring_index(substring_index(cat,',',n),',',-1)) as cat

from   t join (select 1 as n union all select 2 union all select 3) r
       on cat like concat('%',repeat(',%',n-1))