将一张表中的多行合并到 SQL 查询结果集中的多列中

Posted

技术标签:

【中文标题】将一张表中的多行合并到 SQL 查询结果集中的多列中【英文标题】:Merging multiple rows from one table into multiple colums in a SQL Query Result Set 【发布时间】:2013-09-04 15:37:11 【问题描述】:

我正在为一份新报告提取一个基本查询,但遇到了这个小问题。

我有两个表 Buildings (B) 和 Pictures (P) 两者中的键是 BuildingNumber。我在两个表之间有一个简单的内部联接。我遇到的问题是我在B中有183栋建筑物,但是每栋建筑物都有多张图片,并且每栋建筑物的图片数量并不一致。所以当我得到结果集时,它返回了大约 260 行。我想做的是只为每座建筑物返回一行,并为与该建筑物关联的每张图片有一列。请记住,我无权更改或创建表格。

我的数据是这样的:

建筑表(B):

BuildingNumber   BldgName   Floors   SqFt

  0001           Science       5     50000
  0002           Engineering   4     40000

图片表(P):

BuildingNumber     PictureURL

   0001                URL1
   0001                URL2
   0001                URL3  
   0002                URL1 
   0002                URL2

所以我想要的结果是这样设置的:

BuildingNumber   BldgName   Floors   SqFt   PictureURL1   PictureURL2   PictureURL3

    0001         Science        5     50000       URL1        URL2         URL3
    0002         Engineering    4     40000       URL1        URL2          NULL

【问题讨论】:

为了澄清这个问题,您希望行尾的列数是动态的吗? 正确。我不知道每栋建筑有多少张照片。 最好是执行 2 个查询,在你的程序中你可以匹配图片和建筑物 【参考方案1】:

您可以使用PIVOT 函数获取结果,该函数将您的数据行转换为列。

如果每个建筑物的PictureURLs 数量有限,则可以对查询进行硬编码:

select BuildingNumber, bldgname, floors, sqft,
  PictureURL1, PictureURL2, PictureURL3
from
(
  select b.BuildingNumber, b.bldgname, b.floors, b.sqft,
    p.PictureURL,
    col = 'PictureURL'+
            cast(row_number() over(partition by b.BuildingNumber
                                    order by b.BuildingNumber) as varchar(10))
  from building b
  inner join picture p
    on b.BuildingNumber = p.BuildingNumber
) d
pivot
(
  max(PictureURL)
  for col in (PictureURL1, PictureURL2, PictureURL3)
) piv;

见SQL Fiddle with Demo。但是,如果您有未知数量的值,那么您将不得不考虑使用动态 SQL。这将创建一个 sql 字符串,该字符串将被执行以获得最终结果:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('PictureURL'+
                                                      cast(row_number() over(partition by BuildingNumber
                                                                              order by BuildingNumber) as varchar(10))) 
                    from Picture
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT BuildingNumber, bldgname, floors, sqft,' + @cols + ' 
            from 
            (
              select b.BuildingNumber, b.bldgname, b.floors, b.sqft,
                p.PictureURL,
                col = ''PictureURL''+
                        cast(row_number() over(partition by b.BuildingNumber
                                                order by b.BuildingNumber) as varchar(10))
              from building b
              inner join picture p
                on b.BuildingNumber = p.BuildingNumber
            ) x
            pivot 
            (
                max(PictureURL)
                for col in (' + @cols + ')
            ) p '

execute sp_executesql @query;

见SQL Fiddle with Demo。两者都给出结果:

| BUILDINGNUMBER |    BLDGNAME | FLOORS |  SQFT | PICTUREURL1 | PICTUREURL2 | PICTUREURL3 |
|              1 |     Science |      5 | 50000 |        URL1 |        URL2 |        URL3 |
|              2 | Engineering |      4 | 40000 |        URL1 |        URL2 |      (null) |

【讨论】:

单引号应该在那里吗?我尝试了有无,但仍然没有得到结果集。 @Jake 哪个单引号? 澄清一下,在SELECT前面的"Set @query = " @Jake 设置查询正在创建一个 sql 字符串,因此需要单引号。 谢谢先生。我真的很感谢你在这方面的帮助。我得到了第二个查询来运行并提取我需要的所有相关数据。

以上是关于将一张表中的多行合并到 SQL 查询结果集中的多列中的主要内容,如果未能解决你的问题,请参考以下文章

Oracle中的多行插入查询(从一张表中选择多行并插入到另一张表中[重复]

sql如何将一张表中的一列数据分为两列显示

sql server里如何将一组用逗号分隔的字符串分解并插入到另一张表中,比如:11873,27827, 也可能是好多

sql 将多行显示为一行,如果一张表中有几行数据中的同一列的值是相同,那么只显示为一行的数据

如何用SQL语句向一个表中插入多行记录

如何用SQL语句向一个表中插入多行记录