Idealmente, la soluzione migliore sarebbe normalizzare Table2 in modo da non archiviare un elenco separato da virgole.
Una volta che hai normalizzato questi dati, puoi facilmente interrogarli. La nuova struttura della tabella potrebbe essere simile a questa:
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')
;
La normalizzazione delle tabelle renderebbe molto più semplice eseguire query sui dati unendo le tabelle:
select t2.col1, t1.col2
from t2
inner join t1
on t2.col2 = t1.col1
Guarda la demo
Quindi, se desideri visualizzare i dati come un elenco separato da virgole, puoi utilizzare FOR XML PATH
e 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;
Vedi Demo.
Se non sei in grado di normalizzare i dati, ci sono diverse cose che puoi fare.
Innanzitutto, puoi creare una funzione di divisione che converte i dati archiviati nell'elenco in righe su cui è possibile unire. La funzione di divisione sarebbe simile a questa:
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;
Quando usi la funzione di divisione, puoi lasciare i dati in più righe oppure puoi concatenare i valori in un elenco separato da virgole:
;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
Vedi Demo.
Un ultimo modo per ottenere il risultato è applicare FOR XML PATH
direttamente.
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;
Vedi SQL Fiddle con demo