我想生成一个数据透视表,每个数据透视列有2个总和聚合。然后在枢轴列的右侧,我想要一些总列。最后,枢轴列的数量是动态的。我的首选结果如下:
我的数据如下:
从this回答,我已经非常接近解决它了。这就是我所拥有的:
SELECT *
FROM (
SELECT B.SiteID, R.BuildingID, C.*
FROM Rooms R JOIN Buildings B
ON R.BuildingID = B.BuildingID
CROSS APPLY (
VALUES(RTRIM(RoomType) + ' NASF', AreaNASF)
,(RTRIM(RoomType) + ' RSF', AreaRSF)
) C (Item,Value)
) src
PIVOT (
SUM([Value])
FOR [Item] IN ([CONFERENCE NASF], [CONFERENCE RSF], [OFFICE NASF], [OFFICE RSF], [STORAGE NASF], [STORAGE RSF])
) pvt
产生:
我得到的印象是我必须在SQL之外执行两行标题。我需要帮助的是如何添加总列数。另外,除了我见过许多地方的STUFF
解决方案之外,还有更好的动态列解决方案吗?
以下是创建示例数据的SQL:
CREATE TABLE Buildings (
BuildingID CHAR(12),
SiteID CHAR(12),
Name VARCHAR(100),
CONSTRAINT PK_Building PRIMARY KEY (BuildingID)
);
CREATE TABLE Rooms (
BuildingID CHAR(12),
FloorID CHAR(4),
RoomID CHAR(8),
RoomType CHAR(16),
Dept CHAR(16),
AreaNASF NUMERIC(12,2),
AreaRSF NUMERIC(12,2),
CONSTRAINT FK_Rooms_BuildingID FOREIGN KEY (BuildingID) REFERENCES Buildings(BuildingID),
CONSTRAINT PK_Rooms PRIMARY KEY (BuildingID, FloorID, RoomID)
);
INSERT INTO Buildings (BuildingID, SiteID, Name) VALUES
('100', 'Main', 'Headquarters'),
('200', 'Main', 'Technology'),
('300', 'Fleet', 'Fleet')
INSERT INTO Rooms (BuildingID, FloorID, RoomID, RoomType, Dept, AreaNASF, AreaRSF) VALUES
('100', '01', '101', 'CONFERENCE', 'FINANCE', 206.84, 207.00)
,('100', '01', '102', 'OFFICE', 'FINANCE', 100.55, 101.00)
,('100', '01', '103', 'OFFICE', 'FINANCE', 100.87, 101.00)
,('100', '02', '201', 'STORAGE', 'FINANCE', 56.15, 0.00)
,('100', '02', '202', 'CONFERENCE', 'FINANCE', 164.93, 160.00)
,('200', '01', '101', 'OFFICE', 'IT', 95.50, 96.00)
,('200', '01', '102', 'OFFICE', 'IT', 100.64, 100.00)
,('200', '01', '103', 'CONFERENCE', 'IT', 220.19, 220.00)
,('200', '01', '104', 'STORAGE', 'IT', 50.25, 0.00)
,('200', '02', '201', 'OFFICE', 'HR', 65.82, 66.00)
,('300', '01', '101', 'OFFICE', 'MAINTENANCE', 65.82, 66.00)
,('300', '01', '102', 'OFFICE', 'MAINTENANCE', 65.82, 66.00)
答案 0 :(得分:1)
这是使用sum()Over()
窗口聚合函数的一种方法。这里的诀窍是在转动之前为每个AreaNASF/AreaRSF
预先聚合BuildingID
列
SELECT *
FROM (SELECT B.SiteID,
R.BuildingID,
TotalAreaNASF,
TotalAreaRSF,
C.*
FROM (SELECT TotalAreaNASF = Sum(AreaNASF)OVER(partition BY BuildingID),
TotalAreaRSF= Sum(AreaRSF)OVER(partition BY BuildingID),*
FROM Rooms) R
JOIN Buildings B
ON R.BuildingID = B.BuildingID
CROSS APPLY ( VALUES(Rtrim(RoomType) + ' NASF',AreaNASF),
(Rtrim(RoomType) + ' RSF',AreaRSF) ) C (Item, Value)) src
PIVOT ( Sum([Value])
FOR [Item] IN ([CONFERENCE NASF],
[CONFERENCE RSF],
[OFFICE NASF],
[OFFICE RSF],
[STORAGE NASF],
[STORAGE RSF]) ) pvt
如果RoomTypes
的数量未知,则此处为动态版本
declare @col_list varchar(max),
@sql varchar(max)
set @col_list = stuff((select distinct ','+QUOTENAME(Rtrim(RoomType) + ' NASF')+','+QUOTENAME(Rtrim(RoomType) + ' RSF') from #Rooms for xml path('')),1,1,'')
set @sql = '
SELECT SiteID, BuildingID, '+@col_list+', [Total NASF], [Total RSF]
FROM (SELECT B.SiteID,
R.BuildingID,
[Total NASF],
[Total RSF],
C.*
FROM (SELECT [Total NASF] = Sum(AreaNASF)OVER(partition BY BuildingID),
[Total RSF] = Sum(AreaRSF)OVER(partition BY BuildingID),*
FROM Rooms) R
JOIN Buildings B
ON R.BuildingID = B.BuildingID
CROSS APPLY ( VALUES(Rtrim(RoomType) + '' NASF'',AreaNASF),
(Rtrim(RoomType) + '' RSF'',AreaRSF) ) C (Item, Value)) src
PIVOT ( Sum([Value])
FOR [Item] IN ('+@col_list+') ) pvt '
print @sql
exec (@sql)