我想生成一个数据透视表,每个透视列有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)
最佳答案 这是使用sum()Over()窗口聚合函数的一种方法.这里的诀窍是在旋转之前为每个BuildingID预先聚合AreaNASF / AreaRSF列
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)