在单个结果中连接一对多字段?

JOA*_*MON 7 sql-server-2008 join syntax group-concatenation

假设我有以下查询:

SELECT * 
FROM AppDetails, AppTags 
WHERE AppDetails.AppID = '1' 
  AND AppDetails.AppID = AppTags.AppID
Run Code Online (Sandbox Code Playgroud)

这给出了以下结果:

AppID    AppName        AppType    Tag
1        Application1   Utility    Test1
1        Application1   Utility    Test2
1        Application1   Utility    Test3
Run Code Online (Sandbox Code Playgroud)

如何修改查询以返回如下内容:

AppID    AppName        AppType    Tags
1        Application1   Utility    Test1,Test2,Test3
Run Code Online (Sandbox Code Playgroud)

Tar*_*ryn 10

不幸的是,SQL Server 没有一个函数来执行组连接,但有几种不同的方法可以获得结果。

您可以实施FOR XML PATHSTUFF()

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';
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo

或者你可以用FOR XML PATHCROSS 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';
Run Code Online (Sandbox Code Playgroud)

请参阅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%'
Run Code Online (Sandbox Code Playgroud)

演示

如果TagName包含某些 XML 字符(例如>, &),它们将被实体化(>-> >, &-> &)。为避免这种情况,请更改FOR XML PATH('')FOR XML PATH, TYPE).value(N'.[1]',N'nvarchar(max)')