Eins-zu-viele-Feld in einem einzigen Ergebnis verketten?

7

Angenommen, ich habe die folgende Abfrage:

SELECT * 
FROM AppDetails, AppTags 
WHERE AppDetails.AppID = '1' 
  AND AppDetails.AppID = AppTags.AppID

Welches ergibt die folgenden Ergebnisse:

AppID    AppName        AppType    Tag
1        Application1   Utility    Test1
1        Application1   Utility    Test2
1        Application1   Utility    Test3

Wie kann ich die Abfrage so ändern, dass sie Folgendes zurückgibt:

AppID    AppName        AppType    Tags
1        Application1   Utility    Test1,Test2,Test3
Des Teufels Anwalt
quelle

Antworten:

10

Leider verfügt SQL Server nicht über eine einzige Funktion zum Durchführen einer Gruppenverkettung. Es gibt jedoch verschiedene Möglichkeiten, das Ergebnis zu erhalten.

Sie können implementieren FOR XML PATHund 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';

Siehe SQL Fiddle mit Demo .

Oder Sie könnten verwenden FOR XML PATHmit 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';

Siehe SQL Fiddle mit Demo .

Wenn Sie dann die tagsWerte abfragen möchten, können Sie einen CTE verwenden, der ähnlich ist wie:

;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%'

Siehe Demo

Wenn TagNameenthält bestimmte XML - Zeichen (zB >, &) werden sie in Entitäten geworden ( >-> >, &-> &). Um dies zu vermeiden, wechseln Sie FOR XML PATH('')zu FOR XML PATH, TYPE).value(N'.[1]',N'nvarchar(max)').

Taryn
quelle