【问题标题】:SQL 2005 Merge / concatenate multiple rows to one columnSQL 2005 合并/连接多行到一列
【发布时间】:2010-05-13 15:35:07
【问题描述】:

我们有一点 SQL 困惑。假设我有一个看起来像这样的结果......

61E77D90-D53D-4E2E-A09E-9D6F012EB59C |一个
61E77D90-D53D-4E2E-A09E-9D6F012EB59C |乙
61E77D90-D53D-4E2E-A09E-9D6F012EB59C | C
61E77D90-D53D-4E2E-A09E-9D6F012EB59C | D
7ce953ca-a55b-4c55-a52c-9d6f012ea903 |电子
7ce953ca-a55b-4c55-a52c-9d6f012ea903 | F

有没有办法可以在 SQL 中对这些结果进行分组以返回为

61E77D90-D53D-4E2E-A09E-9D6F012EB59C | A B C D
7ce953ca-a55b-4c55-a52c-9d6f012ea903 |英法

有什么想法吗?

非常感谢

戴夫

【问题讨论】:

  • 您应该能够通过将 STUFF() 与 ROW_COUNT() 组合来做到这一点。不过,我不是 TSQL 专家...

标签: sql sql-server-2005 tsql


【解决方案1】:

试试这个:

set nocount on;
declare @t table (id char(36), x char(1))
insert into @t (id, x)
select '61E77D90-D53D-4E2E-A09E-9D6F012EB59C' , 'A' union
select '61E77D90-D53D-4E2E-A09E-9D6F012EB59C' , 'B' union
select '61E77D90-D53D-4E2E-A09E-9D6F012EB59C' , 'C' union
select '61E77D90-D53D-4E2E-A09E-9D6F012EB59C' , 'D' union
select '7ce953ca-a55b-4c55-a52c-9d6f012ea903' , 'E' union
select '7ce953ca-a55b-4c55-a52c-9d6f012ea903' , 'F'
set nocount off

SELECT p1.id, 
          stuff(
                   (SELECT
                        ' ' + x
                        FROM @t p2
                        WHERE p2.id=p1.id
                        ORDER BY id, x
                        FOR XML PATH('') 
                   )
                   ,1,1, ''
               ) AS YourValues
      FROM @t p1
      GROUP BY id

输出:

id                                   YourValues
------------------------------------ --------------
61E77D90-D53D-4E2E-A09E-9D6F012EB59C A B C D
7ce953ca-a55b-4c55-a52c-9d6f012ea903 E F

(2 row(s) affected)

编辑
根据 OP 关于需要为现有查询运行的评论,试试这个:

;WITH YourBugQuery AS
(
    --replace this with your own query
    select '61E77D90-D53D-4E2E-A09E-9D6F012EB59C' AS ColID , 'A' AS ColX 
    union select '61E77D90-D53D-4E2E-A09E-9D6F012EB59C' , 'B' 
    union select '61E77D90-D53D-4E2E-A09E-9D6F012EB59C' , 'C' 
    union select '61E77D90-D53D-4E2E-A09E-9D6F012EB59C' , 'D' 
    union select '7ce953ca-a55b-4c55-a52c-9d6f012ea903' , 'E' 
    union select '7ce953ca-a55b-4c55-a52c-9d6f012ea903' , 'F'

)
SELECT p1.ColID, 
          stuff(
                   (SELECT
                        ' ' + ColX
                        FROM YourBugQuery p2
                        WHERE p2.ColID=p1.ColID
                        ORDER BY ColID, ColX
                        FOR XML PATH('') 
                   )
                   ,1,1, ''
               ) AS YourValues
      FROM YourBugQuery p1
      GROUP BY ColID

这与上面显示的结果集相同。

【讨论】:

  • 谢谢 - 但我可能应该指出结果来自 SQL 查询,所以我无法预测结果将是什么以便我将它们逐行合并。
  • @Dave,在我的示例代码中,我使用所有 UNION 来填充我的表 @t,它们与解决方案无关,只是将数据放入表中以进行查询的一种方式。我将编辑问题以使用 CTE,因此您可以使其适用于任何查询(第一个示例代码适用于表)。
  • 感谢您的帮助,但我最终使用了聚合函数,因为这将在其他地方帮助我们。不过也投了赞成票。
  • 如果您有大量行,嵌套的子选择让我觉得可能非常慢。
  • 我喜欢这个解决方案。很好地完成了我需要的事情。将其改编为我的复杂查询,效果很好。有问题..这个解决方案在大约 10 分钟内帮助了我。谢谢一吨!现在我只需要拆开看看它是如何工作的,这样我就可以自己构建这样的新解决方案。 =)
【解决方案2】:

我更喜欢定义一个自定义的用户定义聚合。 Here's an example 的 UDA 将完成与您所要求的非常接近的事情。

为什么使用用户定义的聚合而不是嵌套的 SELECT?一切都与性能有关,以及您愿意忍受的一切。对于少量元素,您当然可以使用嵌套 SELECT,但对于较大的“n”,您会注意到查询计划基本上对输出列表中的每一行运行一次嵌套 SELECT。如果您正在谈论大量行,这可能是死亡之吻。使用 UDA,可以一次聚合这些值。

当然,要权衡的是 UDA 要求您使用 CLR 来部署它,而这并不是很多人经常做的事情。在 Oracle 中,这种特殊情况要好一些,因为您可以使用 PL/SQL directly 创建用户定义的聚合,但我离题了...

【讨论】:

  • 谢谢,这对我们来说是最好的实现。
  • 我不知道为什么这被否决了;我对它投了赞成票,因为它似乎是一个合法的(并且可能是优雅的)解决方案,也回答了原始问题。 @Dave – 了解为什么这对你来说是最好的答案会很有用(对于找到这个问题及其答案的其他人)。
  • 谢谢。我阐述了我的回答。看,现在你会否决它;-)
【解决方案3】:

另一种方法是使用 FOR XML PATH 选项

SELECT
    [ID],
    (
        SELECT
            [Value] + ' '
        FROM
            [YourTable] [YourTable2]
        WHERE
            [YourTable2].[ID] = [YourTable].[ID]
        ORDER BY
            [Value]
        FOR XML PATH('')
    ) [Values]
FROM
    [YourTable]
GROUP BY
    [YourTable].[ID]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多