每周后添加总计行

Add a Total row after each week

我正在寻找一种按周对列求和的方法。 这是初始 table 数据。

Date            WeekNo      Col1        Col2        Col3
2020/07/01      27           1           4          3
2020/07/04      27           3           3          1
2020/07/06      28           1           1          1
2020/07/11      28           1           3          8

我想像这样在每个周末添加一行总计:

Date            WeekNo      Col1        Col2        Col3
2020/07/01      27           1           4          3
2020/07/04      27           3           3          1
TOTAL           27           4           7          4
2020/07/06      28           1           1          1
2020/07/11      28           1           3          8
TOTAL           28           2           4          9

我尝试了与下面的代码类似的方法,但我有多个列要求和。 您还有其他想法、建议吗?

此外,如果该周没有要求和的数据(例如 0 或 NULL),分组集不会创建新行。

SELECT
    YEAR(Date) AS OrderYear,
    MONTH(Date) AS OrderMonth,
    SUM(Col1) AS SumCol1
FROM tb
GROUP BY
    GROUPING SETS
    (
        YEAR(Date), --1st grouping set
        (YEAR(Date),MONTH(Date)) --2nd grouping set
    )

您只需在列出其他非聚合列 Date,Col1, Col2, Col3 后添加 (DATEPART(wk, Date)) 作为聚合规则。顺便说一句,你不需要 WeekNo 列,因为它可能已经是计算机使用 (DATEPART(wk, Date)).

到目前为止一切顺利,但是排序是一项艰巨的任务,因为要为小计的 WeekNo 列返回空值。我使用了两个解析函数(ROW_NUMBER()FISRT_VALUE() 来解决这个问题):

SELECT COALESCE(Date,'TOTAL') As Date, 
       DATEPART(wk, Date) AS WeekNo,
       SUM(Col1) AS Col1,
       SUM(Col2) AS Col2,
       SUM(Col3) AS Col3                       
FROM tb
GROUP BY GROUPING SETS ( ( Date,Col1, Col2, Col3 ),
                           (DATEPART(wk, Date))        
                         )
ORDER BY CASE WHEN DATEPART(wk, Date) IS NULL 
              THEN
               ROW_NUMBER() OVER (PARTITION BY DATEPART(wk, Date)  
                              ORDER BY COALESCE(Date,'TOTAL') )
              ELSE
               DATEPART(wk, Date) -
               FIRST_VALUE(DATEPART(wk, Date)) 
                    OVER ( ORDER BY COALESCE(Date,'TOTAL') ) + 1               
              END,
         DATEPART(wk, Date)   

Demo

这就是你想要的吗?

我的解决方案使用内置的 with rollup 添加到 group by 子句。

-- create sample data
declare @data table
(
    [Date] Date,
    WeekNo int,
    Col1 int,
    Col2 int,
    Col3 int
);

insert into @data ([Date], WeekNo, Col1, Col2, Col3) values
('2020-07-01', 27, 1, 4, 3),
('2020-07-04', 27, 3, 3, 1),
('2020-07-06', 28, 1, 1, 1),
('2020-07-11', 28, 1, 3, 8);

-- solution
select  case when grouping(d.Date) = 0
            then convert(nvarchar(10), d.Date) -- type conversion so all column values have the same type
            else 'TOTAL'
        end as 'Date',
        d.WeekNo,
        sum(d.Col1) as 'Col1',
        sum(d.Col2) as 'Col2',
        sum(d.Col3) as 'Col3'
from @data d
group by d.WeekNo, d.Date with rollup -- "roll up" the aggregations
having grouping(d.WeekNo) = 0; -- filter out aggregation across weeks

给我:

Date       WeekNo      Col1        Col2        Col3
---------- ----------- ----------- ----------- -----------
2020-07-01 27          1           4           3
2020-07-04 27          3           3           1
TOTAL      27          4           7           4
2020-07-06 28          1           1           1
2020-07-11 28          1           3           8
TOTAL      28          2           4           9