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

将一个表中的多行合并到SQL查询结果集中的多个列中,sql,sql-server,pivot,Sql,Sql Server,Pivot,我正在为一份新报告做一个基本的查询,遇到了这个小问题 我有两个表建筑物(B)和图片(p)。两个表中的关键是建筑物编号。我在两个表之间有一个简单的内部连接。我遇到的问题是,我有183栋建筑在B区,但每栋建筑都有多张图片,而且每栋建筑的图片数量并不一致。因此,当我得到结果集时,它将返回大约260行。我想做的是为每个建筑返回一行,并为每个与该建筑相关联的图片创建一列。请记住,我无权更改或创建表 我的数据如下: BuildingNumber BldgName Floors SqFt Pi

我正在为一份新报告做一个基本的查询,遇到了这个小问题

我有两个表
建筑物
(B)和
图片
(p)。两个表中的关键是建筑物编号。我在两个表之间有一个简单的内部连接。我遇到的问题是,我有183栋建筑在B区,但每栋建筑都有多张图片,而且每栋建筑的图片数量并不一致。因此,当我得到结果集时,它将返回大约260行。我想做的是为每个建筑返回一行,并为每个与该建筑相关联的图片创建一列。请记住,我无权更改或创建表

我的数据如下:

BuildingNumber   BldgName   Floors   SqFt   PictureURL1   PictureURL2   PictureURL3

    0001         Science        5     50000       URL1        URL2         URL3
    0002         Engineering    4     40000       URL1        URL2          NULL
建筑表(B):

图片表(p):

因此,我期望的结果如下所示:

BuildingNumber   BldgName   Floors   SqFt   PictureURL1   PictureURL2   PictureURL3

    0001         Science        5     50000       URL1        URL2         URL3
    0002         Engineering    4     40000       URL1        URL2          NULL
您可以使用该函数获取结果,该函数将数据行转换为列

如果每个建筑的
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。这将创建一个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;
看。两者都给出了一个结果:

| BUILDINGNUMBER |    BLDGNAME | FLOORS |  SQFT | PICTUREURL1 | PICTUREURL2 | PICTUREURL3 |
|              1 |     Science |      5 | 50000 |        URL1 |        URL2 |        URL3 |
|              2 | Engineering |      4 | 40000 |        URL1 |        URL2 |      (null) |
您可以使用该函数获取结果,该函数将数据行转换为列

如果每个建筑的
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。这将创建一个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;
看。两者都给出了一个结果:

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

为了澄清这个问题,您希望在行的末尾有一个动态的列数?正确。我不知道每个建筑有多少张图片。最好是执行2个查询,在程序中可以匹配图片和建筑。为了澄清问题,您希望在行的末尾有动态的列数?正确。我真的不知道每个建筑有多少张图片。最好是执行2个查询,在你的程序中,你可以匹配图片和建筑。单引号应该在那里吗?我尝试了带和不带,但仍然没有得到结果集。@Jake哪个单引号?为了澄清,在“set@query=“@Jake”后面的SELECT前面,set查询正在创建一个sql字符串,因此单引号必须存在。谢谢先生。我真的很感谢你在这方面的帮助。我运行了第二个查询并提取了我需要的所有相关数据。单引号应该在那里吗?我尝试了带和不带,但仍然没有得到结果集。@Jake哪个单引号?为了澄清,在“set@query=“@Jake”后面的SELECT前面,set查询正在创建一个sql字符串,因此单引号必须存在。谢谢先生。我真的很感谢你在这方面的帮助。我运行了第二个查询,并提取了我需要的所有相关数据。