V ideálním případě by bylo vaším nejlepším řešením normalizovat tabulku 2, takže neukládáte seznam oddělený čárkami.
Jakmile máte tato data normalizovaná, můžete je snadno dotazovat. Nová struktura tabulky by mohla být podobná této:
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')
;
Normalizace tabulek by vám mnohem snadněji usnadnila dotazování na data spojením tabulek:
select t2.col1, t1.col2
from t2
inner join t1
on t2.col2 = t1.col1
Viz Demo
Pokud byste pak chtěli data zobrazit jako seznam oddělený čárkami, můžete použít FOR XML PATH
a 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;
Viz Demo.
Pokud nejste schopni normalizovat data, můžete udělat několik věcí.
Nejprve můžete vytvořit funkci rozdělení, která převede data uložená v seznamu na řádky, které lze spojit. Funkce rozdělení by byla podobná této:
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;
Když použijete funkci rozdělení, můžete buď ponechat data ve více řádcích, nebo můžete hodnoty zřetězit zpět do seznamu odděleného čárkami:
;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
Viz Demo.
Posledním způsobem, jak získat výsledek, je použití FOR XML PATH
přímo.
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;
Viz SQL Fiddle with Demo