【问题标题】:Using ROLLUP and GROUPING SETS to format results使用 ROLLUP 和 GROUPING SETS 格式化结果
【发布时间】:2015-11-09 20:57:13
【问题描述】:

我正在尝试学习 SQL Server 2008 R2 中的 ROLLUPGROUPING SETS 运算符。我的桌子是这样的:

+-------+---------+------------+------+--------+--- --------+------+ |企业ID |员工姓名 |开始日期 |类型 |单位 |帐户 |区 | +-------+---------+------------+------+--------+--- --------+------+ | 11111 |爱丽丝 | 2015-09-04 | SD20 | 0.500 | 560.2200 | 100 | | 11111 |爱丽丝 | 2015-09-08 | CCS | 1.330 | 9P0.6010 | 38 | | 11111 |爱丽丝 | 2015-09-08 | CCS | 2.170 | 010.9055 | 62 | | 11111 |爱丽丝 | 2015-09-10 | SD20 | 0.500 | LP0.3002 | 100 | | 11111 |爱丽丝 | 2015-09-14 | SD20 | 0.500 | LP0.3002 | 100 | | 11111 |爱丽丝 | 2015-09-17 | SD20 | 1.000 | LP0.P303 | 100 | | 11111 |爱丽丝 | 2015-09-18 | SD20 | 1.000 | 600.2200 | 100 | | 11111 |爱丽丝 | 2015-09-24 | SD20 | 1.000 | LP0.3002 | 100 | | 11111 |爱丽丝 | 2015-09-25 | SD20 | 1.000 | LP0.3002 | 100 | | 11111 |爱丽丝 | 2015-09-29 | SD20 | 1.000 | LP0.3002 | 100 | | 33333 |卡罗尔 | 2015-09-03 | SD20 | 1.000 | 9P0.PP10 | 100 | | 33333 |卡罗尔 | 2015-09-04 | SD20 | 0.200 | 600.6P62 | 20 | | 33333 |卡罗尔 | 2015-09-04 | SD20 | 0.800 | 600.6P62 | 80 | | 33333 |卡罗尔 | 2015-09-25 | SD20 | 1.000 | P50.2100 | 100 | +-------+---------+------------+------+--------+--- --------+------+

我希望 EmpID 和 EmpName 显示每个员工一次,单位按类型小计,并按 EmpID、类型、帐户排序,如下所示:

+-------+---------+----------------+--------+------ ----+ |企业ID |员工姓名 |类型 |单位 |帐户 | +-------+---------+----------------+--------+------ ----+ | 11111 |爱丽丝 | | | | | | | CCS | 2.17 | 010.9055 | | | | CCS | 1.33 | 9P0.6010 | | | |小计 | 3.5 | | | | | SD20 | 0.5 | 560.2200 | | | | SD20 | 1 | 600.2200 | | | | SD20 | 4 | LP0.3002 | | | | SD20 | 1 | LP0.P303 | | | |小计 | 6.5 | | | 33333 |卡罗尔 | | | | | | | SD20 | 1 | 600.6P62 | | | | SD20 | 1 | 9P0.PP10 | | | | SD20 | 1 | P50.2100 | | | |小计 | 3 | | +-------+----------+----------------+--------+------ ----+

这是我的查询

select 
case
    when Account is null and Type is null then cast(EmpID as varchar(10))
    else ''
end SubEIN, 
case
    when Account is null and Type is null then EmpName 
    else ''
end SubName, 
case
    when Account is null and Type is not null then 'Subtotal:'
    else isnull(Type, '')
end Type, 
case
    when Account is null and Type is null then ''
    else cast(Units as varchar(10)) 
end Units, 
isnull(Account, '')
from (
    select EmpID, EmpName, Type, sum(Units) AS Units, Account
    from mytable
    group by grouping sets ((EmpID, EmpName), (EmpID, EmpName, Type), (EmpID, EmpName, Account, Type))
) x
order by x.EmpName, x.Type, x.Units, x.Account

我可以使用ROLLUP 和/或GROUPING SETS 运算符而不是所有CASE 表达式来获得我想要的吗?

【问题讨论】:

标签: sql-server sql-server-2008 sql-server-2008-r2


【解决方案1】:

我相信 GROUP BY WITH CUBE 运算符将使您接近最终目标。使用这种方法,您可以选择过滤行或更改空值的显示方式。

select 
    EmpID, 
    EmpName, 
    [Type], 
    Units, 
    Account
from 
    (   
        select 
            EmpID, 
            EmpName, 
            [Type], 
            sum(Units) AS Units, 
            Account
        from mytable
        group by EmpID, EmpName, [Type], Account with CUBE
    ) s
where s.yourfilter

链接:https://technet.microsoft.com/en-us/library/ms175939(v=sql.90).aspx

【讨论】:

    【解决方案2】:

    我认为您对 ROLLUP 的期望过高 - 这是我的建议示例,我无法完全摆脱 CASE-s,但结果看起来像您的目标:

    DECLARE @Data TABLE (
        EmpID INT,
        EmpName VARCHAR(100),
        StartDate DATE,
        [Type] VARCHAR(10),
        Units DECIMAL(10, 3),
        Account VARCHAR(100),
        Dist INT
    );
    
    INSERT INTO
        @Data
    VALUES
        (11111, 'Alice', '2015-09-04', 'SD20', 0.500, '560.2200', 100),
        (11111, 'Alice', '2015-09-08', 'CCS',  1.330, '9P0.6010',  38),
        (11111, 'Alice', '2015-09-08', 'CCS',  2.170, '010.9055',  62),
        (11111, 'Alice', '2015-09-10', 'SD20', 0.500, 'LP0.3002', 100),
        (11111, 'Alice', '2015-09-14', 'SD20', 0.500, 'LP0.3002', 100),
        (11111, 'Alice', '2015-09-17', 'SD20', 1.000, 'LP0.P303', 100),
        (11111, 'Alice', '2015-09-18', 'SD20', 1.000, '600.2200', 100),
        (11111, 'Alice', '2015-09-24', 'SD20', 1.000, 'LP0.3002', 100),
        (11111, 'Alice', '2015-09-25', 'SD20', 1.000, 'LP0.3002', 100),
        (11111, 'Alice', '2015-09-29', 'SD20', 1.000, 'LP0.3002', 100),
        (33333, 'Carol', '2015-09-03', 'SD20', 1.000, '9P0.PP10', 100),
        (33333, 'Carol', '2015-09-04', 'SD20', 0.200, '600.6P62',  20),
        (33333, 'Carol', '2015-09-04', 'SD20', 0.800, '600.6P62',  80),
        (33333, 'Carol', '2015-09-25', 'SD20', 1.000, 'P50.2100', 100)
    
    
    SELECT
        CASE
            WHEN RN = 0 THEN OrigEmpID
            ELSE NULL 
            END AS EmpID,
        CASE
            WHEN RN = 0 THEN EmpName
            ELSE NULL 
            END AS EmpName,
        CASE
            WHEN RN = 0 THEN NULL
            WHEN RN = 3 THEN 'Subtotal' 
            ELSE [OrigType] 
            END AS [Type],
        Units,
        Account
    FROM (
        SELECT DISTINCT
            0 AS RN,
            EmpID AS OrigEmpID, 
            EmpName,
            cast(NULL AS VARCHAR(10)) AS [OrigType],
            cast(NULL AS DECIMAL(10,3)) AS Units,
            cast(NULL AS VARCHAR(100)) AS Account
        FROM
            @Data
    
        UNION ALL
    
        SELECT
            CASE WHEN Account IS NULL THEN 3 ELSE 2 END RN,
            EmpID AS OrigEmpID, 
            EmpName, 
            [Type] AS [OrigType],
            sum(Units) AS Units, 
            Account
        FROM
            @Data
        GROUP BY 
            EmpID, EmpName, [Type], ROLLUP(Account)
    ) data
    ORDER BY
        OrigEmpID, [OrigType], RN, Account
    

    【讨论】:

      猜你喜欢
      • 2014-10-06
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      • 1970-01-01
      • 2016-05-14
      • 2012-06-03
      • 1970-01-01
      相关资源
      最近更新 更多