Idealerweise wäre Ihre beste Lösung, Table2 zu normalisieren, sodass Sie keine durch Kommas getrennte Liste speichern.
Sobald Sie diese Daten normalisiert haben, können Sie die Daten einfach abfragen. Die neue Tabellenstruktur könnte etwa so aussehen:
CREATE TABLE T1
(
[col1] varchar(2),
[col2] varchar(5),
constraint pk1_t1 primary key (col1)
);
INSERT INTO T1
([col1], [col2])
VALUES
('C1', 'john'),
('C2', 'alex'),
('C3', 'piers'),
('C4', 'sara')
;
CREATE TABLE T2
(
[col1] varchar(2),
[col2] varchar(2),
constraint pk1_t2 primary key (col1, col2),
constraint fk1_col2 foreign key (col2) references t1 (col1)
);
INSERT INTO T2
([col1], [col2])
VALUES
('R1', 'C1'),
('R1', 'C2'),
('R1', 'C4'),
('R2', 'C3'),
('R2', 'C4'),
('R3', 'C1'),
('R3', 'C4')
;
Das Normalisieren der Tabellen würde es Ihnen viel einfacher machen, die Daten abzufragen, indem Sie die Tabellen verbinden:
select t2.col1, t1.col2
from t2
inner join t1
on t2.col2 = t1.col1
Siehe Demo
Wenn Sie die Daten dann als kommagetrennte Liste anzeigen möchten, können Sie FOR XML PATH
verwenden und STUFF
:
select distinct t2.col1,
STUFF(
(SELECT distinct ', ' + t1.col2
FROM t1
inner join t2 t
on t1.col1 = t.col2
where t2.col1 = t.col1
FOR XML PATH ('')), 1, 1, '') col2
from t2;
Siehe Demo.
Wenn Sie die Daten nicht normalisieren können, gibt es mehrere Möglichkeiten, die Sie tun können.
Erstens könnten Sie eine Aufteilungsfunktion erstellen, die die in der Liste gespeicherten Daten in Zeilen umwandelt, die verknüpft werden können. Die Split-Funktion wäre ähnlich wie diese:
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;
Wenn Sie die Split-Funktion verwenden, können Sie die Daten entweder in mehreren Zeilen belassen oder die Werte wieder zu einer durch Kommas getrennten Liste verketten:
;with cte as
(
select c.col1, t1.col2
from t1
inner join
(
select t2.col1, i.items col2
from t2
cross apply dbo.split(t2.col2, ',') i
) c
on t1.col1 = c.col2
)
select distinct c.col1,
STUFF(
(SELECT distinct ', ' + c1.col2
FROM cte c1
where c.col1 = c1.col1
FOR XML PATH ('')), 1, 1, '') col2
from cte c
Siehe Demo.
Eine letzte Möglichkeit, das Ergebnis zu erhalten, ist die Anwendung von FOR XML PATH
direkt.
select col1,
(
select ', '+t1.col2
from t1
where ','+t2.col2+',' like '%,'+cast(t1.col1 as varchar(10))+',%'
for xml path(''), type
).value('substring(text()[1], 3)', 'varchar(max)') as col2
from t2;
Siehe SQL Fiddle mit Demo