【问题标题】:Rolling count of rows withing time interval [duplicate]时间间隔内的滚动行数[重复]
【发布时间】:2021-06-26 23:41:43
【问题描述】:

对于分析,我需要根据创建时间聚合单个表的行。基本上,我想知道在当前订单之前的某个时间段内创建的订单数量。似乎找不到解决办法。

表结构:

order_id time_created
1 00:00
2 00:01
3 00:03
4 00:05
5 00:10

预期结果:

order_id count within 3 seconds
1 1
2 2
3 3
4 2
5 1

【问题讨论】:

    标签: sql postgresql count subquery


    【解决方案1】:

    听起来类似于window functions 的应用程序。但是,可悲的是,事实并非如此。窗口框架只能基于行数,而不是实际的列值。

    使用LEFT JOIN 的简单查询就可以完成这项工作:

    SELECT t0.order_id
         , count(t1.time_created) AS count_within_3_sec
    FROM   tbl      t0
    LEFT   JOIN tbl t1 ON t1.time_created BETWEEN t0.time_created - interval '3 sec'
                                              AND t0.time_created
    GROUP  BY 1
    ORDER  BY 1;
    

    db小提琴here

    不适用于您的最小演示中的time,因为它不会环绕。我认为假设 timestamptimestamptz 是合理的。

    由于您将每一行本身包含在计数中,INNER JOIN 也可以工作。 (LEFT JOIN 面对可能的 NULL 值仍然更可靠。)

    或使用LATERAL 子查询,您不需要在外部查询级别进行聚合:

    SELECT t0.order_id
         , t1.count_within_3_sec
    FROM   tbl t0
    LEFT   JOIN LATERAL (
       SELECT count(*) AS count_within_3_sec
       FROM   tbl t1
       WHERE  t1.time_created BETWEEN t0.time_created - interval '3 sec'
                                  AND t0.time_created
       ) t1 ON true
    ORDER  BY 1;
    

    相关:

    对于时间范围内的大表和许多行,遍历表一次的程序解决方案将表现更好。喜欢:

    【讨论】:

    • 感谢编辑和查询解决方案。正如您已经指出的那样,对于一张大桌子(不幸的是我有),程序解决方案似乎是更好的方法。我现在正在尝试根据您的 PL/pgSQL 程序解决方案来实现。
    • 您确定有明显优于联接的程序解决方案吗?当然,我可以遍历所有记录,然后查询三秒内的记录数,但如果我没记错的话,这与连接一样昂贵。我已经研究了您的程序解决方案(来自您的链接),这是一个非常优雅的解决方案,但它只有在每条记录都映射到结果中的一行时才有效,这在我的场景中是不正确的。也许我忽略了一些东西......
    • @MikeAndIke:是的,我很确定。但这比我提供的示例要复杂一些。我调查并找到了另一个相关的答案(在上面添加)。我实际上正在关闭这个问题,因为另一个问题完全回答了你的问题。
    猜你喜欢
    • 1970-01-01
    • 2015-08-13
    • 1970-01-01
    • 2012-11-18
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-24
    相关资源
    最近更新 更多