Sql 如何将多行合并为一行?

Sql 如何将多行合并为一行?,sql,sql-server,join,union,pivot,Sql,Sql Server,Join,Union,Pivot,所以我整天都在寻找解决这个问题的好办法,结果却一无所获。假设我有一张类似的桌子: 投影位置BilledSoFar NotBilled ---------------------------------------------------- EE123 AA1 100 200 EE456 MNGR 4000 500 EE123 AA3 43 0 EE012规范1435 4355 .... .... .... ....

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

投影位置BilledSoFar NotBilled
----------------------------------------------------
EE123 AA1 100 200
EE456 MNGR 4000 500
EE123 AA3 43 0
EE012规范1435 4355
.... .... .... ....

我试图做的是用同一个projectd获取多行,并将所有这些行合并成一行。我需要每个项目ID的“Position”“BilledSoFar”和“NotBilled”,即使ProjectID不存在Position,如下所示:

投射
----------------------------------------------------------------------------------------------------------------
EE123 AA1 100 200 AA3 43 0 MNGR空值

等等

因此,我需要将给定项目ID的所有记录放在一行中,即使该projectID不存在职位(上面的例子是MNGR,它不是EE123下的职位),我也必须拥有所有职位和账单信息(如果projectID不存在该职位,则该信息显然为空)。我试过pivot、joins,并考虑过一个并集,但仍然无法理解这一点,我已经猜不到了

我还应该注意到,我知道有固定数量的投影(比如3400个)和固定数量的位置(比如20个)


谢谢

您可以使用递归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
  • 正如所建议的,这应该在客户端应用程序中完成,但如果只完成一次,那么我将使用上面发布的简单复制粘贴方法

您可以创建一个接受所需projectID作为参数的过程

使用光标() 循环遍历与项目匹配的行,以构建字段的分隔字符串

返回字符串或从字符串生成select语句并执行它

例如,要执行从游标生成的选择字符串:

SELECT 'EE123' AS 'ProjectID',
       'AA1', 
       '100', 
       '200', 
       'AA3', 
       '43', 
       '0', 
       'MNGR', 
       'Null', 
       'Null' 
FROM <tablaname> 
WHERE 1=1
选择'EE123'作为'ProjectID',
"AA1",,
'100', 
'200', 
"AA3",,
'43', 
'0', 
“MNGR”,
“空”,
“空”
从…起
其中1=1

您知道每个项目有多少个位置吗?如果您事先知道所有项目,并且项目的数量是固定的,那么您可以做到这一点,但我猜情况并非如此。一般来说,这不是sql要做的事情。我建议检索多行,然后在您的数据库中组装它们应用程序,无论是“客户端”应用程序,还是最坏的情况,在存储过程中。嘿,伙计们,来回答你们的问题:eaolson-我们知道有多少个位置,总共大约有20个。Justin-我们使用SQL Server。Grey-是的,这就是为什么将此任务传递给我是如此痛苦的原因。我会手动执行,但有数千个很多项目都需要这个。我也知道所有的项目。我做了一个选择不同的项目来检索每一个单独的项目,它只是让数据以这种方式运行,这就是诀窍。这是我需要做的一件事来生成一个报告,所以如果我能让它在数据上工作,只要我做好了。谢谢大家。