如何将多行合并为一行?

Posted

技术标签:

【中文标题】如何将多行合并为一行?【英文标题】:How can I combine multiple rows into one row? 【发布时间】:2012-05-03 02:35:52 【问题描述】:

所以我整天都在寻找解决这个问题的好方法,但结果却一无所获。假设我有一个类似这样的表:

ProjectID 位置 BilledSoFar NotBilled -------------------------------------------------- -- EE123      AA1       100              200 EE456      MNGR   4000            500 EE123     AA3      43            0 EE012     SPEC1   435           4355 ....        ....                                                                                                                                                                                                                                                                                               ...

我正在尝试做的是获取具有相同 projectID 的多行,并将所有这些行合并为一个。我需要每个项目 ID 的“Position”“BilledSoFar”和“NotBilled”,即使 ProjectID 不存在 Position,如下所示: 项目 ID ----------------------------------------------- -------------------------------------------------- --------------- EE123      AA1      100      200      AA3      43      0      MNGR      Null      Null        ......

等等。

所以我需要将给定项目 ID 的所有记录放在一行中,即使该项目 ID 不存在位置(上面的示例是 MNGR,它不是 EE123 下的位置)我也必须拥有所有职位和计费信息(如果 projectID 不存在该职位,则显然为 NULL)。我已经尝试过枢轴,加入并考虑过联合但仍然无法解决这个问题,而且我在这里的猜测已经不多了。

我还应该注意,我知道有固定数量的 projectid(比如 3400)和固定数量的 Position(比如 20 个)。

谢谢。

【问题讨论】:

你知道每个projectID有多少个职位吗? 如果您事先知道所有的 ProjectID,并且它们的数量是固定的,那么您可以完成这项工作,但我猜情况并非如此。一般来说,这不是 sql 要做的事情。我建议检索多行,然后在您的应用程序中组装它们,无论是“客户端”应用程序,还是最坏的情况,在存储过程中。 大家好,回答您的问题: eaolson - 我们知道有多少职位,总共大约有 20 个。贾斯汀 - 我们使用 SQL Server。 Grey- 是的,这就是为什么把这个任务交给我是一件很痛苦的事情。我会手动完成,但有成千上万的项目需要这个。我也知道所有这些项目。我已经做了一个 select distinct 来检索每个单独的,它只是让数据以这种方式运行,这就是诀窍。这是我需要做的一次性事情来生成报告,所以如果我可以让它在我好的时候处理数据。谢谢大家。 【参考方案1】:

您可以使用递归 CTE 将其展平,但这不会将值放在单独的列中,而是将它们放在一个逗号分隔的列中。如果这对您不起作用:

您可以使用非常复杂的动态 SQL 创建来即时执行下一个选项(它只会创建所需的列数(如果不需要扩展到 20 列) 您可以对很长的左连接进行硬编码,因为您知道行数不会超过 20 行并且只需要一次:

看起来像这样:

SELECT ProjectID, Position, BilledSoFar, NotBilled, 
    ROW_NUMBER() OVER (PARTITION BY ProjectID ORDER BY Position) AS RowNum
INTO #ProjectTable
FROM ProjectTable

SELECT ProjectTable.ProjectID, 
    ProjectTable.Position AS Position1, ProjectTable.BilledSoFar AS BilledSoFar1, 
    ProjectTable.NotBilled AS NotBilled1, 
    ProjectTable2.Position AS Position2, ProjectTable2.BilledSoFar AS BilledSoFar2, 
    ProjectTable2.NotBilled AS NotBilled2, 
    ...
    ProjectTable20.Position AS Position20, ProjectTable20.BilledSoFar AS BilledSoFar20, 
    ProjectTable20.NotBilled AS NotBilled20 
FROM #ProjectTable AS ProjectTable
    LEFT JOIN #ProjectTable AS ProjectTable2
        ON ProjectTable.ProjectID = ProjectTable2.ProjectID AND ProjectTable2.RowNum = 2
    ...
    LEFT JOIN #ProjectTable AS ProjectTable20
        ON ProjectTable.ProjectID = ProjectTable20.ProjectID AND ProjectTable20.RowNum = 20
WHERE ProjectTable.RowNum = 1
按照建议,这应该在客户端应用程序中完成,但如果只完成一次,那么我会使用上面发布的简单复制和粘贴方法

【讨论】:

【参考方案2】:

您可以创建一个接受所需项目 ID 作为参数的过程。

使用光标 (http://justgeeks.blogspot.com/2008/08/using-t-sql-cursor-in-sql-server.html) 循环遍历与 projectID 匹配的行以构建字段的分隔字符串。

返回字符串或从字符串中构建一个选择语句并执行它。

例如从 CURSOR 构建的要执行的选择字符串:

SELECT 'EE123' AS 'ProjectID',
       'AA1', 
       '100', 
       '200', 
       'AA3', 
       '43', 
       '0', 
       'MNGR', 
       'Null', 
       'Null' 
FROM <tablaname> 
WHERE 1=1

【讨论】:

以上是关于如何将多行合并为一行?的主要内容,如果未能解决你的问题,请参考以下文章

怎样将多行数字合并到一行中?

如何将共享 id 的多行合并为一行(PYSPARK)

如何快速批量将多行的内容,变成一行?

利用Oracle分析函数实现多行数据合并为一行

PostgreSQL:如何将多行的值放在不同的列中,并将所有值合并到一行中?

SQL 多行多列数据清洗合并为一行