Rya*_*yan 5 t-sql sql-server pivot aggregate pivot-table
我想生成一个数据透视表,每个数据透视列有 2 个总和聚合。然后在枢轴列的右侧,我想要一些总列。最后,枢轴列的数量是动态的。我的首选结果如下:
我的数据如下所示:
从这个答案来看,我已经非常接近解决它了。这是我所拥有的:
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
Run Code Online (Sandbox Code Playgroud)
其产生:
我的印象是我必须在 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)
Run Code Online (Sandbox Code Playgroud)
这是使用窗口聚合函数的一种方法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
Run Code Online (Sandbox Code Playgroud)
如果数量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)
Run Code Online (Sandbox Code Playgroud)