【问题标题】:PostgreSQL: Aggregate daily sum over list of durationsPostgreSQL:在持续时间列表中汇总每日总和
【发布时间】:2016-10-08 14:23:02
【问题描述】:

现状

我有一张表可以跟踪特定资源的使用情况。它看起来像这样:

started   | timestamp with time zone | not null
last_ping | timestamp with time zone |
stopped   | timestamp with time zone |

stoppedlast_ping 字段可能为空。如果它们都被填满,则stopped 是相关的。

开始日期和结束日期只能跨越几秒钟或多个日期。

目标

我想获取过去 14 天的每日使用情况列表。

当前状态

我知道我可以获得过去 14 天的列表:

SELECT day
FROM generate_series(CURRENT_DATE, CURRENT_DATE - 14, '-1 day'::interval) day;

我可以得到每个使用条目的总时长:

SELECT COALESCE(stopped, last_ping, started) - started AS duration
FROM api_sessionusage;

我还可以结合这两个查询并添加一个仅考虑到午夜的持续时间的限制:

SELECT
  day,
  (
    SELECT SUM(
      LEAST(COALESCE(stopped, last_ping, started), day + interval '1 day') - started
    )
    FROM api_sessionusage
    WHERE started >= day AND started < day + interval '1 day'
  ) AS aggregated_duration
FROM generate_series(CURRENT_DATE, CURRENT_DATE -14, '-1 day'::interval) day;

这里的问题是,午夜之后结束的使用会话只计算在起始日,但不考虑午夜之后的持续时间。

如何重写查询以便获得过去 14 天内每天的汇总使用情况?

【问题讨论】:

  • 我认为具有所需输出的示例表数据在这里会有所帮助。

标签: sql postgresql subquery aggregate


【解决方案1】:

使用时间戳范围类型的overlap and intersect operators

select 
    day, 
    sum(upper(daily_range) - lower(daily_range))
from (
    select 
        day, 
        session_range * tstzrange(day, day::date + 1) daily_range
    from generate_series(current_date, current_date -14, '-1 day'::interval) day
    left join (
        select tstzrange(started, coalesce(stopped, last_ping, started)) session_range
        from api_sessionusage
        ) s
    on session_range && tstzrange(day, day::date + 1)
) s
group by 1
order by 1;

注意。

coalesce(stopped, last_ping, started) - started as duration

如果stoppedlast_ping 都为空,则结果为零。也许应该是

coalesce(stopped, last_ping, current_date) --?

【讨论】:

  • 哇,这是一个很棒的查询。我不知道这些运营商:) 谢谢!
  • 我想我发现了一个错误 - 两个 tstzrange(day::date - 1, day) 调用应该是 tstzrange(day, day::date + 1),对吧?
  • 是的,一个逻辑错误;)谢谢,答案已更新。
猜你喜欢
  • 2019-06-23
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 2012-01-09
  • 2018-09-15
相关资源
最近更新 更多