带有ROW和列总计的SQL动态数据透视表

时间:2018-07-24 01:52:59

标签: sql-server tsql pivot dynamic-pivot

E_ID Full_name      Dept        fy_week fy_rev
45  Tom Smith       Sales       201801  100
65  Mike Tod        Marketing   201801  50
12  Chris Thomson   Sales       201803  60
85  Paul Henry      Sales       201804  40
32  Mich Dowell     Sales       201802  50
65  Mike Tod        Marketing   201803  70
12  Chris Thomson   Sales       201802  80
85  Paul Henry      Sales       201803  90

我在SQL表中有上述数据。我可以通过Dynamic Pivot查询创建下表而不使用Total列。在枢轴列之前需要总计列,在底部需要总计列。

E_ID Full_name      Dept    Total   201801  201802  201803  201804
12  Chris Thomson   Sales   $140        $0      $80 $60     $0
32  Mich Dowell     Sales    $50        $0      $50  $0     $0
45  Tom Smith       Sales   $100      $100       $0  $0     $0
65  Mike Tod    Marketing   $120       $50       $0 $70     $0
85  Paul Henry      Sales   $130        $0       $0 $90    $40
Total                       $540      $150     $130 $220       $40

过去曾问过类似的问题,但我未能根据自己的需要进行重构。这是我的代码:

DECLARE 
@cols   AS NVARCHAR(MAX), @query  AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(fy_week) y
        FROM my_sample_table z
        ORDER BY y asc
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

set @query = 'SELECT e_id, full_name, dept, ' + @cols + ' 
    from ( select e_id, full_name, dept from my_sample_table ) x
       pivot 
        ( Sum(fy_rev) for fy_week in (' + @cols + ')) p '
execute(@query)

1 个答案:

答案 0 :(得分:1)

假设:

  • fy_week是字符串数据类型

要获取列总计,请添加到您的查询x

from 
( 
    -- your original query
    select E_ID, Full_name, Dept, fy_week, fy_rev -- you missed the fy_week & fy_rev here
    from   my_sample_table 

    -- add the following few lines : union all & select query
    union all

    select E_ID, Full_name, Dept, fy_week = ''Total'', fy_rev = sum(fy_rev)
    from   my_sample_table 
    group by E_ID, Full_name, Dept
) x

和@cols将需要附加列名称Total。将以下内容添加到您的set @cols查询

后的之后
select  @cols = '[Total],' + @cols

对于行级查询,您将需要另一个按fy_week分组的查询,为此,我使用了CTE,因为您需要两次引用上述x查询

完整查询。 (我重新格式化了一下)

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

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(fy_week) y
            FROM my_sample_table z
            ORDER BY y asc
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')

SET @cols = '[Total],' + @cols           -- added this line

-- added cte query
SET @query  = '
    ; with cte as
    (
            select  E_ID, Full_name, Dept, 
                    fy_week = convert(varchar(10), fy_week), fy_rev 
            from    my_sample_table 

            union all

            select  E_ID, Full_name, Dept, 
                    fy_week = ''Total'', fy_rev = sum(fy_rev) 
            from    my_sample_table 
            group by E_ID, Full_name, Dept
    )
    SELECT E_ID, Full_name, Dept, ' 
        + @cols + ' 
    from 
    ( 
        select  E_ID, Full_name, Dept, fy_week, fy_rev 
        from    cte

        -- the following is for row wise total
        union all

        select  E_ID = 99, Full_name = ''Total'', Dept = '''', fy_week, sum(fy_rev) 
        from    cte 
        group by fy_week
    ) x
    pivot 
    ( 
        Sum(fy_rev) 
        for fy_week in (' + @cols + ')
    ) p '

-- print out to validate
print   @query
execute(@query)

编辑:处理fy_week的更改是一个整数列