Idéalement, votre meilleure solution serait de normaliser Table2 afin de ne pas stocker une liste séparée par des virgules.
Une fois ces données normalisées, vous pouvez facilement interroger les données. La nouvelle structure du tableau pourrait ressembler à ceci :
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 normalisation des tables faciliterait grandement l'interrogation des données en joignant les tables :
select t2.col1, t1.col2
from t2
inner join t1
on t2.col2 = t1.col1
Voir la démo
Ensuite, si vous souhaitez afficher les données sous forme de liste séparée par des virgules, vous pouvez utiliser FOR XML PATH
et 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;
Voir la démo.
Si vous n'êtes pas en mesure de normaliser les données, vous pouvez faire plusieurs choses.
Tout d'abord, vous pouvez créer une fonction de fractionnement qui convertira les données stockées dans la liste en lignes pouvant être jointes. La fonction split serait similaire à ceci :
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;
Lorsque vous utilisez la fonction split, vous pouvez soit laisser les données dans plusieurs lignes, soit concaténer les valeurs dans une liste séparée par des virgules :
;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
Voir la démo.
Une dernière façon d'obtenir le résultat consiste à appliquer FOR XML PATH
directement.
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;
Voir SQL Fiddle avec démo