首先,你最好的解決方案是不將數據存儲在數據庫中的一個逗號分隔的列表。您應該考慮修復表結構。
如果你不能改變表結構,那麼你將需要在列表中的數據拆分行指定正確的名稱。數據分割後,您可以將數據連接回列表中。
有許多不同的split
功能,你可以在網上卻發現這裏是一個版本,我通常使用:和
CREATE FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))
returns @temptable TABLE (items varchar(MAX))
as
begin
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert into @temptable(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end;
爲了讓您的結果,我會通過應用split
函數開始,因爲我一個row_number()
沒有看到與每一行關聯的唯一密鑰。如果您對各行的唯一鍵,那麼你將不需要0:
;with cte as
(
select rn, name, id
from
(
select row_number() over(order by (select 1)) rn,
databasename
from table2
) t2
cross apply dbo.split(t2.databasename, ',') i
inner join table1 t1
on i.items = t1.id
)
select *
from cte
此查詢傷了你的逗號分隔的列表分爲以下幾個:
| RN | NAME | ID |
--------------------
| 1 | MSSQL | 1 |
| 1 | Oracle | 3 |
| 2 | MySQl | 2 |
| 3 | MSSQL | 1 |
| 3 | MySQl | 2 |
一旦你在多個數據用正確的name
行,那麼你可以使用STUFF()
和FOR XML PATH
將其連接成列表。您的完整查詢將與此類似:
;with cte as
(
select rn, name, id
from
(
select row_number() over(order by (select 1)) rn,
databasename
from table2
) t2
cross apply dbo.split(t2.databasename, ',') i
inner join table1 t1
on i.items = t1.id
)
select
STUFF(
(SELECT ', ' + c2.name
FROM cte c2
where c1.rn = c2.rn
order by c2.id
FOR XML PATH (''))
, 1, 1, '') Databasename
from cte c1
group by c1.rn
order by c1.rn;
請參閱SQL Fiddle with Demo。
完整查詢的結果是:
| DATABASENAME |
------------------
| MSSQL, Oracle |
| MySQl |
| MSSQL, MySQl |
在數據庫中存儲逗號分隔的名單是不是一個好的做法。對此的查詢將非常可怕。 – 2013-02-16 14:18:07
搜索'SQL中的分割函數'你會得到很多。 – Kaf 2013-02-16 14:21:35
爲什麼人們一直這樣做?這與使用姓氏作爲唯一鍵一樣是一個基本的錯誤。 – 2013-10-26 10:58:58