我该如何修改这个SQL语句?

时间:2010-09-29 17:22:03

标签: sql sql-server-2005 tsql group-by concatenation

我的SQL Server视图

SELECT     
   geo.HyperLinks.CatID, geo.Tags.Tag, geo.HyperLinks.HyperLinksID
FROM
   geo.HyperLinks LEFT OUTER JOIN
       geo.Tags INNER JOIN
       geo.TagsList ON geo.Tags.TagID = geo.TagsList.TagID ON geo.HyperLinks.HyperLinksID = geo.TagsList.HyperLinksID WHERE HyperLinksID = 1

返回这些......

HyperLinksID CatID Tags
1            2     Sport
1            2     Tennis
1            2     Golf

如何修改上述内容以获得

等结果
HyperLinksID CatID TagsInOneRowSeperatedWithSpaceCharacter
1            2     Sport Tennis Golf

更新:正如布拉德建议我来到这里......

DECLARE @TagList varchar(100)
SELECT @TagList = COALESCE(@TagList + ', ', '') + CAST(TagID AS nvarchar(100))
FROM TagsList
WHERE HyperLinksID = 1
SELECT @TagList

现在结果看起来像

HyperLinksID CatID TagsInOneRowSeperatedWithSpaceCharacter
1            2     ID_OF_Sport ID_OF_Tennis ID_OF_Golf

当然,我必须合并来自 @TagList变量和原始 SELECT声明......

这意味着我将不得不等待神圣的SO赏金:(

3 个答案:

答案 0 :(得分:11)

如果是SQL,请尝试以下帖子:

Concatenating Row Values

如果您想尝试使用CLR代码,可以再次为MS SQL创建用于连接的自定义聚合函数。

This post非常详尽,有很多方法可以实现你的目标。

答案 1 :(得分:4)

如果您的标记名称包含特殊的XML字符,请使用方法from here来避免任何问题:。

;With HyperLinks As
(
SELECT 1 AS HyperLinksID, 2 AS CatID
),
TagsList AS
(
SELECT 1 AS TagId, 1 AS HyperLinksID UNION ALL
SELECT 2 AS TagId, 1 AS HyperLinksID UNION ALL
SELECT 3 AS TagId, 1 AS HyperLinksID
)
,
Tags AS
(
SELECT 1 AS TagId, 'Sport' as Tag UNION ALL
SELECT 2 AS TagId, 'Tennis' as Tag UNION ALL
SELECT 3 AS TagId, 'Golf' as Tag 
)
SELECT HyperLinksID,
       CatID       ,
      (SELECT mydata
       FROM    ( SELECT Tag AS [data()]
               FROM    Tags t
                       JOIN TagsList tl
                       ON      t.TagId = tl.TagId
               WHERE   tl.HyperLinksID = h.HyperLinksID 
               ORDER BY t.TagId 
               FOR XML PATH(''), TYPE
               ) AS d ( mydata ) FOR XML RAW,
               TYPE
       )
       .value( '/row[1]/mydata[1]', 'varchar(max)' ) TagsInOneRowSeperatedWithSpaceCharacter
FROM   HyperLinks h

编辑:正如KM在评论中指出的那样,此方法实际上会自动添加空格,因此我删除了手动添加的空格。对于除逗号Peter's answer之类的空格以外的分隔符似乎更合适。

如果您知道您的数据不包含任何有问题的字符,那么更简单(可能更高性能)的版本

SELECT CatID       ,
       HyperLinksID,
       stuff(
       ( SELECT ' ' + Tag 
               FROM    Tags t
                       JOIN TagsList tl
                       ON      t.TagId = tl.TagId
               WHERE   tl.HyperLinksID = h.HyperLinksID 
               ORDER BY t.TagId 
               FOR XML PATH('')
       ), 1, 1, '') TagsInOneRowSeperatedWithSpaceCharacter
FROM   HyperLinks h

答案 2 :(得分:2)

在相关子查询中使用FOR XML。对于以空格分隔的列表:

SELECT h.HyperLinksID, h.CatID
, TagList = (
    SELECT t.Tag AS [data()]
    FROM geo.TagList l
    JOIN geo.Tags t ON l.TagId = t.TagId
    WHERE l.HyperLinksID = h.HyperLinksID
    ORDER BY t.Tag
    FOR XML PATH(''), TYPE
  ).value('.','NVARCHAR(MAX)')
FROM geo.HyperLinks AS h
WHERE h.HyperLinksID = 1

对于任何其他分隔符:

SELECT h.HyperLinksID, h.CatID
, TagList = STUFF((
      SELECT ', '+t.Tag
      FROM geo.TagList l
      JOIN geo.Tags t ON l.TagId = t.TagId
      WHERE l.HyperLinksID = h.HyperLinksID
      ORDER BY t.Tag
      FOR XML PATH(''), TYPE
    ).value('.','NVARCHAR(MAX)')
  ,1,2,'')
FROM geo.HyperLinks AS h
WHERE h.HyperLinksID = 1

子查询创建一个分隔列表,然后STUFF(...,1,2,'')删除前导,TYPE).value()解决了XML中特殊字符的最常见问题。