For det første er din bedste løsning ikke at gemme data i en kommasepareret liste i din database. Du bør overveje at rette tabelstrukturen.
Hvis du ikke kan ændre tabelstrukturen, bliver du nødt til at opdele dataene på listen i rækker for at tildele det korrekte navn. Når dataene er opdelt, kan du sammenkæde dataene tilbage til listen.
Der er mange forskellige split
funktion, som du kan finde online, men her er en version, som jeg typisk bruger:
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;
For at få dit resultat, ville jeg starte med at anvende split
funktion og en row_number()
da jeg ikke kan se en unik nøgle forbundet med hver række. Hvis du har en unik nøgle på hver række, behøver du ikke 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
Denne forespørgsel opdeler din kommaseparerede liste i følgende:
| RN | NAME | ID |
--------------------
| 1 | MSSQL | 1 |
| 1 | Oracle | 3 |
| 2 | MySQl | 2 |
| 3 | MSSQL | 1 |
| 3 | MySQl | 2 |
Når du har dataene i flere rækker med det korrekte name
, så kan du bruge STUFF()
og FOR XML PATH
at sammenkæde det i listen. Din fulde forespørgsel ville ligne denne:
;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 af den fulde forespørgsel er:
| DATABASENAME |
------------------
| MSSQL, Oracle |
| MySQl |
| MSSQL, MySQl |