次のクエリがあるとします。
SELECT *
FROM AppDetails, AppTags
WHERE AppDetails.AppID = '1'
AND AppDetails.AppID = AppTags.AppID
次の結果が得られます。
AppID AppName AppType Tag
1 Application1 Utility Test1
1 Application1 Utility Test2
1 Application1 Utility Test3
次のようなものを返すようにクエリを変更するにはどうすればよいですか。
AppID AppName AppType Tags
1 Application1 Utility Test1,Test2,Test3
残念ながら、SQL Serverにはグループ連結を実行する単一の関数はありませんが、結果を得るにはいくつかの方法があります。
_FOR XML PATH
_ および STUFF()
を実装できます。
_SELECT DISTINCT d.AppId,
d.AppName,
d.AppType,
Tags = STUFF((SELECT ', ' + t.TagName
FROM AppTags t
where d.AppID = t.AppID
FOR XML PATH (''))
, 1, 1, '')
FROM AppDetails d
WHERE d.AppID = '1';
_
SQL Fiddle with Demo を参照してください。
または、_FOR XML PATH
_と_CROSS APPLY
_を併用することもできます。
_SELECT DISTINCT d.AppId,
d.AppName,
d.AppType,
tags = left(t.tags, len(t.tags)-1)
FROM AppDetails d
CROSS APPLY
(
SELECT t.TagName + ', '
FROM AppTags t
WHERE d.AppID = t.AppID
FOR XML PATH('')
) t (Tags)
WHERE d.AppID = '1';
_
SQL Fiddle with Demo を参照してください。
次にtags
値に対してクエリを実行する場合は、次のようなCTEを使用できます。
_;with cte as
(
SELECT DISTINCT d.AppId,
d.AppName,
d.AppType,
Tags = STUFF((SELECT ', ' + t.TagName
FROM AppTags t
where d.AppID = t.AppID
FOR XML PATH (''))
, 1, 1, '')
FROM AppDetails d
WHERE d.AppID = '1'
)
select *
from cte
where tags like '%test1%'
_
参照 デモ
TagName
に特定のXML文字(例:_>
_、_&
_)が含まれている場合、これらは文字化されます(_>
_-> _>
_、_&
_-> _&
_)。これを回避するには、FOR XML PATH('')
をFOR XML PATH, TYPE).value(N'.[1]',N'nvarchar(max)')
に変更します。