使用 MS SQL Server 中的 Group by 字段将垂直 sql 结果转换为水平输出

Posted

技术标签:

【中文标题】使用 MS SQL Server 中的 Group by 字段将垂直 sql 结果转换为水平输出【英文标题】:Convert vertical sql result into horizontal output with Group by fields in MS SQL Server 【发布时间】:2014-04-15 03:56:34 【问题描述】:

我有一个包含垂直销售交易数据的表(在 SQL Server 2008 中),我想将垂直输出转换为水平输出,我尝试使用 PIVOT,但有些人不知道如何在 PIVOT 上应用 group by ,因为我想要基于 AccountHeadID、TransType 和 IsPast Column 的 Sum。

示例表

CREATE TABLE Trans
    ([TransID] int,
     [CustID] int,
     [AccountHeadID] int,
     [TransType] varchar(100),
     [IsPast] bit,
     [Amount] int)
;

INSERT INTO Trans
    ([TransID],CustID, [AccountHeadID], [TransType], [IsPast],[Amount])
VALUES
    (1, 1, 1, 'Sales',1,1000),
    (2, 1, 1, 'Sales',0,500),
    (3, 1, 1, 'Sales',0,400),
    (4, 1, 1, 'Return',0,300),
    (5, 1, 1, 'Return',0,200),
    (6, 1, 1, 'Return',0,100),
    (7, 1, 1, 'Return',1,150),
    (8, 1, 2, 'Sales',1,2000)   

当前查询

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(AccountHeadID)  
                    from Trans
                    group by AccountHeadID
                    order by AccountHeadID
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT CustID,' + @cols + ' 
            from 
            (
              SELECT 
                a.CustID,
                a.AccountHeadID,
                 a.TransType,
                 a.Amount,
                 a.isPast
              FROM Trans a
            ) x
            pivot 
            (
                sum(Amount)
                for AccountHeadID in (' + @cols + ')
            ) p '

execute sp_executesql @query;

预期输出

CustID | Account-HeadID-TransType-IsPast[1-Sales-Past] |  Account-HeadID-TransType-IsCurrent[1-Sales-Current] | Account-HeadID-TransType-IsCurrent[1-Return-Past] |  Account-HeadID-TransType-IsCurrent[1-Return-Current] | Account-HeadID-TransType-IsCurrent[2-Sales-Past]| ...
1      |1000                                           | 900 (500 + 400)                                      |150                                                | 600[300+200+100]                                       |2000   

见SQL Fiddle with Demo

欢迎提出任何建议或意见!

谢谢 苏雷什

【问题讨论】:

看看a related SO question,这可能对你有帮助。 【参考方案1】:

试试这个:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(CONVERT(NVARCHAR(10),AccountHeadID) + N'-' + TransType + N'-' + CONVERT(NVARCHAR(10),IsPast))  
                    from Trans
                    group by AccountHeadID, TransType, IsPast
                    order by AccountHeadID, TransType, IsPast
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

--select @cols

set @query = 'SELECT CustID,' + @cols + ' 
            from 
            (
              SELECT 
                a.CustID,
                CONVERT(NVARCHAR(10),AccountHeadID) + N''-'' + TransType + N''-'' + CONVERT(NVARCHAR(10),IsPast) Acct,
                 a.Amount
              FROM Trans a
            ) x
            pivot 
            (
                sum(Amount)
                for Acct in (' + @cols + ')
            ) p '

execute sp_executesql @query;

SQL Fiddle

【讨论】:

感谢您的回答,完美的查询!

以上是关于使用 MS SQL Server 中的 Group by 字段将垂直 sql 结果转换为水平输出的主要内容,如果未能解决你的问题,请参考以下文章

SQL GROUP BY 与 LEFT JOIN MS SQL Server

SQL Server 错误中的 GROUP_CONCAT

GROUP BY 中的 SQL Server 2014 LAST_VALUE

SQL Server中的SQL group_concat函数[重复]

使用属性值从 MS SQL Server 中的 JSON blob 中检索特定值?

SQL Server 2012 中的 group_concat 与 ORDER BY 另一列