从 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))
我有一个 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))