För det första är din bästa lösning att inte lagra data i en kommaseparerad lista i din databas. Du bör överväga att fixa tabellstrukturen.
Om du inte kan ändra tabellstrukturen måste du dela upp data i listan i rader för att tilldela rätt namn. När data är uppdelade kan du sammanfoga data tillbaka till listan.
Det finns många olika split
funktion som du kan hitta online men här är en version som jag vanligtvis använder:
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;
För att få ditt resultat skulle jag börja med att använda split
funktion och en row_number()
eftersom jag inte ser en unik nyckel kopplad till varje rad. Om du har en unik nyckel på varje rad behöver du inte row_number()
:
;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
Den här frågan delar upp din kommaseparerade lista i följande:
| RN | NAME | ID |
--------------------
| 1 | MSSQL | 1 |
| 1 | Oracle | 3 |
| 2 | MySQl | 2 |
| 3 | MSSQL | 1 |
| 3 | MySQl | 2 |
När du har data i flera rader med rätt name
, då kan du använda STUFF()
och FOR XML PATH
för att sammanfoga det i listan. Din fullständiga fråga skulle likna denna:
;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;
Se SQL Fiddle with Demo.
Resultatet av hela frågan är:
| DATABASENAME |
------------------
| MSSQL, Oracle |
| MySQl |
| MSSQL, MySQl |