【问题标题】:Cumulative Sum When Order Was Placed in postgresqlpostgresql下单时的累计金额
【发布时间】:2022-10-25 01:05:12
【问题描述】:

我有一个订单表,其中包含下订单和完成时间的日期时间:

orderid userid price status createdat doneat
1 128 100 completed 2/16/21 18:40:45 2/21/21 07:59:46
2 128 150 completed 2/21/21 05:27:29 2/23/21 11:58:23
3 128 100 completed 9/3/21 08:38:14 9/10/21 14:24:35
4 5 100 completed 5/28/22 23:28:07 6/26/22 06:10:35
5 5 100 canceled 7/8/22 22:28:57 8/10/22 06:55:17
6 5 100 completed 7/25/22 13:46:38 8/10/22 06:57:20
7 5 5 completed 8/7/22 18:07:07 8/12/22 06:56:23

我想要一个新列,它是创建订单时每个用户的累计总额(总价):

orderid userid price status createdat doneat cumulative total when placed (per user)
1 128 100 completed 2/16/21 18:40:45 2/21/21 07:59:46 0
2 128 150 completed 2/21/21 05:27:29 2/23/21 11:58:23 0
3 128 100 completed 9/3/21 08:38:14 9/10/21 14:24:35 250
4 5 100 completed 5/28/22 23:28:07 6/26/22 06:10:35 0
5 5 100 canceled 7/8/22 22:28:57 8/10/22 06:55:17 100
6 5 100 completed 7/25/22 13:46:38 8/10/22 06:57:20 100
7 5 5 completed 8/7/22 18:07:07 8/12/22 06:56:23 100

逻辑是将在当前行创建日期之前完成的所有订单的每个用户的价格相加。对于orderid=2,虽然是用户的第二笔订单,但是在其createdat datetime 2/21/21 05:27:29之前没有完成的订单,所以下单时的累计总数为0。

[5,6,7] 中的 orderid 也是如此。对于这些订单和该用户 ID,在其创建日期之前完成的唯一订单是订单 4,因此下达时的累计总数为 100。

PowerBI中的逻辑是这样的:

SUMX (
filter(
orders, 
earlier orders.userid = orders.userid && orders.doneat < orders.createdat && order.status = 'completed'),
orders.price)

有人对如何在 postgresql 中实现这一点有任何提示吗?

我尝试过这样的事情,但没有奏效。

select (case when o.doneat < o.createdat over (partition by o.userid, o.status order by o.createdat)
    then sum(o.price) over (partition by o.userid, o.status ORDER BY o.doneat asc ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
        end) as cumulativetotal_whenplaced
    from order o

谢谢

【问题讨论】:

    标签: postgresql sum amazon-redshift cumulative-sum


    【解决方案1】:

    您可以将每一行复制到:

    1. 一个“原始”(我们将用标志keep = true 装饰),具有会计价值val = 0(到目前为止)和时间t = createdat
    2. 一个“重复”(keep = false),它的价格(如果状态为'completed')为val 和一个时间t = doneat

      然后只需考虑正确的位即可:

      select orderid, userid, price, status, createdat, doneat, cumtot
      from (
        select *, sum(val) over (partition by userid order by t, keep desc) as cumtot
        from (
          select *, createdat as t, 0 as val, true as keep from foo
          union all
          select *, doneat as t,
            case when status = 'completed' then price else 0 end as val,
            false as keep
          from foo
        ) as a
      ) as a
      where keep
      order by orderid;
      

      示例:DB Fiddle

      RedShift 的注意事项:上面的窗口表达式需要替换为:

         ...
         select *, sum(val) over (
           partition by userid order by t, keep desc
           rows unbounded preceding) as cumtot
         ...
      

      您的数据的结果:

      orderid userid price status createdat doneat cumtot
      1 128 100 completed 2021-02-16T18:40:45.000Z 2021-02-21T07:59:46.000Z 0
      2 128 150 completed 2021-02-21T05:27:29.000Z 2021-02-23T11:58:23.000Z 0
      3 128 100 completed 2021-09-03T08:38:14.000Z 2021-09-10T14:24:35.000Z 250
      4 5 100 completed 2022-05-28T23:28:07.000Z 2022-06-26T06:10:35.000Z 0
      5 5 100 canceled 2022-07-08T22:28:57.000Z 2022-08-10T06:55:17.000Z 100
      6 5 100 completed 2022-07-25T13:46:38.000Z 2022-08-10T06:57:20.000Z 100
      7 5 5 completed 2022-08-07T18:07:07.000Z 2022-08-12T06:56:23.000Z 100

      笔记:这种跨时间的会计类型实际上对许多极端情况(各种订单重叠,一些开始和结束,而另一些仍在进行中等)是稳健的。它是我应该在某天描述的快速间隔压缩算法的基础所以。

      奖励:尝试找出分区窗口按t 排序的原因(相当明显)并且还通过keep desc(不太明显)。

    【讨论】:

    • 您好皮埃尔,感谢您的快速回复。当我尝试运行它时,它要求为 order by 提供一个框架子句。我正在使用的是 redshift,如果这对 postgresql 语言有影响的话。你知道哪个框架条款适合吗?我尝试了一些,但 cumtot 显示为零
    • 我没有意识到您正在使用 Redshift(我只是将标签添加到您的问题中)。 PostgreSQL 和 Redshift 之间有一些重要的区别。例如,在窗口具有ORDER BY 的窗口函数中(如在我们的查询中),那么必须有一个 frame_clause 来定义要考虑的行集。见here。我现在没有连接到 Redshift 集群,所以我不能立即尝试,但我会从文档中将 unbounded preceding 添加到窗口中。
    • 你好皮埃尔,谢谢。我在前面尝试了无界,但由于某种原因,它仍然显示为 0 表示 cumtot,不知道如何排除故障
    猜你喜欢
    • 2017-08-01
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 2017-09-28
    • 2023-03-15
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    相关资源
    最近更新 更多