【问题标题】:A way to have a rolling summation一种滚动求和的方法
【发布时间】:2020-11-05 21:01:15
【问题描述】:

我有以下数据集。在下面 1993 年的示例记录中。Tgrowth 列是 start - endStarted 是在特定月份加入的员工人数,ended 是当月离职的员工人数。

SELECT 
        r.Tgrowth,
            CASE
                WHEN t.mon_num = 1 THEN 'JAN'
                WHEN t.mon_num = 2 THEN 'FEB'
                WHEN t.mon_num = 3 THEN 'MAR'
                WHEN t.mon_num = 4 THEN 'APR'
                WHEN t.mon_num = 5 THEN 'MAY'
                WHEN t.mon_num = 6 THEN 'JUN'
                WHEN t.mon_num = 7 THEN 'JUL'
                WHEN t.mon_num = 8 THEN 'AUG'
                WHEN t.mon_num = 9 THEN 'SEP'
                WHEN t.mon_num = 10 THEN 'OCT'
                WHEN t.mon_num = 11 THEN 'NOV'
                WHEN t.mon_num = 12 THEN 'DEC'
            END AS myMONTH
    FROM
        (SELECT 1 mon_num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) t
    LEFT JOIN Reports r ON t.mon_num = r.theMONTH
        AND r.Tyear = 1993
    GROUP BY r.Tgrowth , myMONTH
    ORDER BY t.mon_num ASC

上面的结果集如下,

Tgrowth Month
1      JAN
0      FEB
2      MAR
0      APR
0      MAY
0      JUN
0      JUL
0      AUG
0      SEP
0      OCT
0      NOV
0      DEC

相反,我希望结果显示滚动总和,即添加到 Tgrowth 字段。像下面这样,

growth  Emp_Count   myMONTH
1          1        JAN
0          1        FEB
2          3        MAR
0          3        APR
0          3        MAY
0          3        JUN
0          3        JUL
0          3        AUG
0          3        SEP
0          3        OCT
0          3        NOV
0          3        DEC

【问题讨论】:

标签: mysql sql date join window-functions


【解决方案1】:

有两种选择:

  1. 使用连接
  2. 使用变量

join的使用方法如下:

SELECT
       t1.Tgrowth,
       sum(t2.Tgrowth) as Emp_Count,
       CASE
        WHEN t1.Month = 1 THEN 'JAN'
        WHEN t1.Month = 2 THEN 'FEB'
        WHEN t1.Month = 3 THEN 'MAR'
        WHEN t1.Month = 4 THEN 'APR'
        WHEN t1.Month = 5 THEN 'MAY'
        WHEN t1.Month = 6 THEN 'JUN'
        WHEN t1.Month = 7 THEN 'JUL'
        WHEN t1.Month = 8 THEN 'AUG'
        WHEN t1.Month = 9 THEN 'SEP'
        WHEN t1.Month = 10 THEN 'OCT'
        WHEN t1.Month = 11 THEN 'NOV'
        WHEN t1.Month = 12 THEN 'DEC'
       END AS myMONTH
FROM (
    SELECT
    case
        when r.growth is not null then r.growth
        when r.growth is null then 0
    END as Tgrowth,
    t.mon_num AS Month
FROM
    (SELECT 1 mon_num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
    UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8
    UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) t
LEFT JOIN Reports r ON t.mon_num = r.themonth
    AND r.theYear = 1993
GROUP BY r.growth , Month
ORDER BY t.mon_num ASC
         ) as t1 join (
    SELECT
    case
        when r.growth is not null then r.growth
        when r.growth is null then 0
    END as Tgrowth,
    t.mon_num AS Month
FROM
    (SELECT 1 mon_num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
    UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8
    UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) t
LEFT JOIN Reports r ON t.mon_num = r.themonth
    AND r.theYear = 1993
GROUP BY r.growth , Month
ORDER BY t.mon_num ASC
         ) as t2 on t1.Month >= t2.Month group by t1.Month;

使用变量解决方案如下:

SET @num := 0;
select
       Tgrowth,
       @num := @num + Tgrowth as Emp_Count,
       CASE
        WHEN t1.Month = 1 THEN 'JAN'
        WHEN t1.Month = 2 THEN 'FEB'
        WHEN t1.Month = 3 THEN 'MAR'
        WHEN t1.Month = 4 THEN 'APR'
        WHEN t1.Month = 5 THEN 'MAY'
        WHEN t1.Month = 6 THEN 'JUN'
        WHEN t1.Month = 7 THEN 'JUL'
        WHEN t1.Month = 8 THEN 'AUG'
        WHEN t1.Month = 9 THEN 'SEP'
        WHEN t1.Month = 10 THEN 'OCT'
        WHEN t1.Month = 11 THEN 'NOV'
        WHEN t1.Month = 12 THEN 'DEC'
       END AS myMONTH
from (
SELECT
    case
        when r.growth is not null then r.growth
        when r.growth is null then 0
    END as Tgrowth,
    t.mon_num AS Month
FROM
    (SELECT 1 mon_num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
    UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8
    UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) t
LEFT JOIN Reports r ON t.mon_num = r.themonth
    AND r.theYear = 1993
GROUP BY r.growth , Month
ORDER BY t.mon_num ASC ) t1;

【讨论】:

    【解决方案2】:

    由于您运行的是 MySQL 8.0,我建议使用递归查询来生成日期,然后是窗口函数和聚合。

    如果你想要整个 1993 年:

    with dates as (
        select '1993-01-01' dt
        union all
        select dt + interval 1 month from dates where dt < '1993-12-01'
    )
    select
        date_format(d.dt, '%b') mymonth,
        coalesce(sum(started), 0) - coalesce(sum(ended), 0) growth,
        sum(coalesce(sum(started), 0) - coalesce(sum(ended), 0)) over(order by d.dt) emp_count
    from dates d
    left join reports r on r.theDate >= d.dt and r.theDate < d.dt + interval 1 month
    group by d.dt
    order by d.dt
    

    这假定theDate 存储为date 数据类型而不是字符串(否则,您需要先转换它,使用str_to_date())。

    这还考虑到表可能包含给定月份的多行的可能性。如果不是这样,则不需要聚合:

    with dates as (
        select '1993-01-01' dt
        union all
        select dt + interval 1 month from dates where dt < '1993-12-01'
    )
    select
        date_format(d.dt, '%b') mymonth,
        coalesce(started, 0) - coalesce(ended, 0) growth,
        sum(coalesce(started, 0) - coalesce(ended, 0)) over(order by d.dt) emp_count
    from dates d
    left join reports r on r.theDate >= d.dt and r.theDate < d.dt + interval 1 month
    order by d.dt
    

    【讨论】:

      猜你喜欢
      • 2011-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 2011-02-21
      相关资源
      最近更新 更多