【问题标题】:How should I modify this SQL statement?我应该如何修改这个 SQL 语句?
【发布时间】:2011-04-18 23:04:03
【问题描述】:

我的 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

当然,我必须将 from the@TagList 变量和 original SELECT 语句的内容...

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

【问题讨论】:

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


    【解决方案1】:

    如果您的标签名称包含特殊的 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 在 cmets 中指出的那样,这种方法实际上会自动添加空格,因此我已经删除了手动添加的空格。对于空格以外的分隔符,如逗号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
    

    【讨论】:

    • 在您的第一个代码示例(试图避免扩展 xml 控制字符)中,您总是在 TagsInOneRowSeperatedWithSpaceCharacter 列中的值后面有两个空格。一个空格似乎是自动的,另一个是您手动附加的空格。不好的部分是自动空格介于值和手动空格之间。试一试,尝试从您的第一个查询中创建此值Sport, Tennis, Golf。你会得到Sport , Tennis , Golf
    • @KM - 非常感谢您让我知道。稍后我会看一下。
    【解决方案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 中包含特殊字符的最常见问题。

    【讨论】:

      【解决方案3】:

      如果是 SQL,试试这个帖子:

      Concatenating Row Values

      如果您想尝试 CLR 代码,这里有一些示例可以创建自定义聚合函数以用于连接,同样适用于 MS SQL。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-31
        • 2019-06-03
        • 1970-01-01
        • 2020-02-13
        • 1970-01-01
        • 1970-01-01
        • 2021-03-15
        • 1970-01-01
        相关资源
        最近更新 更多