まず、最善の解決策は、データベースのコンマ区切りのリストにデータを保存しないことです。テーブル構造の修正を検討する必要があります。
テーブル構造を変更できない場合は、リスト内のデータを行に分割して、正しい名前を割り当てる必要があります。データが分割されたら、データを連結してリストに戻すことができます。
多くの異なるsplit
があります オンラインで見つけることができる機能ですが、これが私が通常使用するバージョンです:
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;
結果を得るには、まずsplit
を適用します 関数とrow_number()
各行に関連付けられた一意のキーが表示されないためです。各行に一意のキーがある場合は、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
このクエリは、カンマ区切りのリストを次のように分割します。
| RN | NAME | ID |
--------------------
| 1 | MSSQL | 1 |
| 1 | Oracle | 3 |
| 2 | MySQl | 2 |
| 3 | MSSQL | 1 |
| 3 | MySQl | 2 |
正しいname
で複数の行にデータを配置したら 、次にSTUFF()
を使用できます およびFOR XML PATH
それをリストに連結します。完全なクエリは次のようになります:
;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;
SQL FiddlewithDemoを参照してください。
完全なクエリの結果は次のとおりです。
| DATABASENAME |
------------------
| MSSQL, Oracle |
| MySQl |
| MSSQL, MySQl |