从MySQL表中检索不同的concat值

时间:2016-12-02 11:20:58

标签: mysql sql database distinct concat

我有一个SQL表格广告

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

4 个答案:

答案 0 :(得分:1)

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))

答案 1 :(得分:0)

我认为你应该改变你的表结构并使它像这样。

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

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

答案 2 :(得分:0)

您应该修复数据结构,这样就不会在列中存储以逗号分隔的列表。这是在关系数据库中存储数据的错误方法。 。 。你可以从回答这个简单问题的问题中看出来。你想要的是一个交接表。

有时,我们会遇到其他人不好的设计。你说只有两个或值,那么你可以这样做:

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;

答案 3 :(得分:0)

首先......我会创建一个语句,将所有行转换为一个大的逗号分隔列表。

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

然后使用本SO文章描述的表值udf split将该大量字符串转换回带有distinct子句的表,以确保它是唯一的。

https://stackoverflow.com/a/2837662/261997

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