sql-server – 具有多个聚合列和总计列的SQL Server PIVOT

我想生成一个数据透视表,每个透视列有2个总和聚合.然后在枢轴列的右侧,我想要一些总列.最后,枢轴列的数量是动态的.我的首选结果如下:

《sql-server – 具有多个聚合列和总计列的SQL Server PIVOT》

我的数据如下:

《sql-server – 具有多个聚合列和总计列的SQL Server PIVOT》

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-server – 具有多个聚合列和总计列的SQL Server PIVOT》

我得到的印象是我必须在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)
点赞