SQL:在SQL查询中返回嵌套值(SQLServer)

时间:2014-05-13 15:07:12

标签: sql-server pivot-table

我想创建一个SQL报告,显示一系列唱片商店的有序库存清单,以显示每个商店的当前库存状态:Nirvana,Mission of Burma和Wipers专辑,假设每个商店只包含一张专辑时间(为了简单起见)。

我的SQL查询当前只显示每个乐队是否有库存的专辑我希望能够显示每张专辑的库存水平所以我认为我需要某种嵌套的返回并可能使用一个支点 - 表而不是左外连接。


Drop table #AlbumStock 
Drop table #MissionOfBurma 
Drop table #Wipers
Drop table #Nirvana
go

CREATE TABLE #AlbumStock 
( Store varchar(Max),
  Artist varchar(Max),
  Album varchar(Max),
  AlbumID int 
)
go

INSERT INTO #AlbumStock 
    (Store,Artist,Album,AlbumID)
VALUES 
    ('Glasgow','Wipers', 'Over the Edge', 3),
    ('Glasgow', 'Nirvana', 'Bleach', 1),
    ('Glasgow', 'Nirvana', 'Unplugged In New York', 4),
    ('Glasgow', 'Mission of burma', 'VS', 1),
    ('Leeds', 'Wipers', 'Over the Edge', 3), 
    ('Leeds','Wipers', 'Youth of America', 2),
    ('Leeds', 'Nirvana', 'Bleach', 1),
    ('Leeds', 'Nirvana', 'Nevermind', 2),
    ('Manchester', 'Wipers', 'Over the Edge', 3),
    ('Manchester', 'Wipers', 'Youth of America', 2),
    ('Manchester', 'Wipers', 'Is this real?', 1),
    ('Manchester', 'Wipers', 'Land of the lost', 4)


Select MAX(AlbumID) As FirstID, Store 
Into #MissionOfBurma 
From #AlbumStock 
Where Artist = 'Mission of burma'
Group BY Store

Select MAX(AlbumID) As FirstID, Store
Into #Wipers 
From #AlbumStock 
Where Artist = 'Wipers'
Group BY Store

Select MAX(AlbumID) As FirstID, Store  
Into #Nirvana 
From #AlbumStock 
Where Artist = 'Nirvana'
Group BY  Store

-- Current Reporting Query

Select stock.Store, ISNULL(mob.FirstID,0) As Mission_of_Burma_ID, 
    ISNULL(wip.FirstID,0) As Wipers_ID, ISNULL(nir.FirstID,0) As Nirvana_ID 
From (Select Store 
      From #AlbumStock 
      Group BY Store ) as stock  
LEFT OUTER JOIN
 #MissionOfBurma as mob 
 ON
 mob.Store = stock.Store
LEFT OUTER JOIN
 #Wipers as wip
 ON
 wip.Store = stock.Store
 LEFT OUTER JOIN
 #Nirvana as nir
 ON
 nir.Store = stock.Store

查询的输出是:

╔════════════╦═════════════════════╦═══════════╦════════════╗
║ Store      ║ Mission_of_Burma_ID ║ Wipers_ID ║ Nirvana_ID ║
╠════════════╬═════════════════════╬═══════════╬════════════╣
║ Glasgow    ║ 1                   ║ 3         ║ 4          ║
║ Leeds      ║ 0                   ║ 3         ║ 2          ║
║ Manchester ║ 0                   ║ 4         ║ 0          ║
╚════════════╩═════════════════════╩═══════════╩════════════╝

我希望它更像是这样的东西:

╔════════════╦═════════════════════╦═══════════╦════════════╗
║ Store      ║ Mission_of_Burma_ID ║ Wipers_ID ║ Nirvana_ID ║
╠════════════╬═════════════════════╬═══════════╬════════════╣
║ Glasgow    ║ 1                   ║ 3         ║ 1  ║ 4     ║
║ Leeds      ║ 0                   ║ 2   ║  3  ║ 1  ║ 2     ║
║ Manchester ║ 0                   ║1 ║ 2║ 3║4 ║ 0          ║
╚════════════╩═════════════════════╩═══════════╩════════════╝

非常感谢任何建议/指导。

1 个答案:

答案 0 :(得分:0)

您面临的第一个问题是SqlServer没有等效的MySql's GROUP_CONCAT,也没有通用的聚合Fold功能。 因此,您需要使用these hacks之一来获取逗号分隔的股票清单,例如STUFF / FOR XML PATH

SELECT Store, Artist, 
   STUFF((SELECT ',' + CAST(albumID AS VARCHAR(10)) 
   FROM #AlbumStock a 
   WHERE a.Store = x.Store AND a.Artist = x.Artist 
   FOR XML PATH ('')), 1, 1, '') AS Stuffed
FROM
(
   SELECT Store, artist
   FROM #AlbumStock
   GROUP BY Store, Artist
) x;

结果如下:

Store       Artist                Stuffed
----------- --------------------------------
Glasgow     Mission of burma      1
Glasgow     Nirvana               1,4
Glasgow     Wipers                3
Leeds       Nirvana               1,2
Leeds       Wipers                3,2
Manchester  Wipers                3,2,1,4

要将每个艺术家作为列进行转换,您需要PIVOT

WITH cteStuffed AS
(
   SELECT Store, Artist, 
      STUFF((SELECT ',' + CAST(albumID AS VARCHAR(10)) 
      FROM AlbumStock a 
      WHERE a.Store = x.Store AND a.Artist = x.Artist 
      FOR XML PATH ('')), 1, 1, '') AS Stuffed
   FROM
   (
      SELECT Store, artist
      FROM AlbumStock
      GROUP BY Store, Artist
   ) x
)
SELECT Store, [Mission of burma], [Wipers], [Nirvana]
FROM
   cteStuffed
PIVOT
(
 MIN(Stuffed)
 for [Artist] IN ([Mission of burma], [Wipers], [Nirvana])
)pvt;

SqlFiddle here

这样就可以为你提供所需的表格,虽然我猜有几个松散的结局:

  • 您可能希望使用ISNULLCOALESCE将零替换为零。
  • 您可能希望从数据中动态确定列。要做到这一点,你需要求助于动态Sql - 看看如何BlueFeet does this here