【问题标题】:MySQL Running Total By Group, Time IntervalMySQL 按组运行总计,时间间隔
【发布时间】:2020-10-16 19:20:39
【问题描述】:

我想要一张这样的客户订单表:

customer_id | order_date | amount
0           | 2020-03-01 | 10.00
0           | 2020-03-02 |  2.00
1           | 2020-03-02 |  5.00
1           | 2020-03-02 |  1.00
2           | 2020-03-08 |  2.00
1           | 2020-03-09 |  1.00
0           | 2020-03-10 |  1.00
0           | 2020-03-16 |  1.00

并创建一个按周计算累积运行总计的表格,从最早的日期(2020-03-01、2020-03-08 等)开始将周划分为 7 天。比如:

customer_id | week_0 | week_1 |  week_2
0           | 12.00  | 13.00  |  14.00 
1           |  6.00  | 7.00   |   7.00
2           |  0.00  | 2.00   |   2.00

感谢您的帮助!

【问题讨论】:

  • 考虑处理应用代码中数据显示的问题。
  • @Scott。 . .你需要解释你是如何定义“周”的。
  • @Strawberry 这相当于应用程序之前的预处理步骤,因此我们不必将所有数据都保存在内存中
  • @Gordon Linoff 谢谢,希望现在更清楚

标签: mysql sql date pivot window-functions


【解决方案1】:

您可以使用聚合和窗口函数(这需要 MySQL 8.0)。将周放在行中比在列中更容易且更具可扩展性:

select
    customer_id,
    year_week(order_date) order_week,
    sum(sum(amount)) over(partition by customer_id order by year_week(order_date)) running_amount
from mytable
group by customer_id, year_week(order_date)
order by customer_id, year_week(order_date)

您也可以将其转为列 - 但您需要列举周数:

select
    customer_id,
    max(case when order_week = 202001 then running_amount end) week_01,
    max(case when order_week = 202002 then running_amount end) week_02,
    max(case when order_week = 202003 then running_amount end) week_03,
    ...
from (
    select
        customer_id,
        year_week(order_date) order_week,
        sum(sum(amount)) over(partition by customer_id order by year_week(order_date)) running_amount
    from mytable
    group by customer_id, year_week(order_date)
) t
order by customer_id

【讨论】:

    【解决方案2】:

    我认为你想要条件聚合——在计算第一个订单日期之后:

    select customer_id,
           sum(case when order_date >= min_order_date + interval 0 day and order_date < min_order_date + interval 7 day
                    then amount else 0
               end) as week_0,
           sum(case when order_date >= min_order_date + interval 7 day and order_date < min_order_date + interval 14 day
                    then amount else 0
               end) as week_1,
           sum(case when order_date >= min_order_date + interval 14 day and order_date < min_order_date + interval 21 day
                    then amount else 0
               end) as week_2
    from (select t.*, min(order_date) over () as min_order_date
          from t
         ) t
    group by customer_id;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 2014-03-30
      • 1970-01-01
      • 2023-01-12
      • 2016-04-15
      • 1970-01-01
      相关资源
      最近更新 更多