【问题标题】:Calculate the sum of a field filtered by a window defined on another field计算由在另一个字段上定义的窗口过滤的字段的总和
【发布时间】:2015-03-15 15:11:40
【问题描述】:

我有桌子event:

event_date,
num_events,
site_id

我可以很容易地使用聚合 SQL 来做SELECT SUM(num_events) GROUP BY site_id

但我还有另一张桌子site

site_id,
target_date

我想做一个 JOIN,在 target_date、90 天、120 天等的 60 天内显示 num_events 的总和。我认为这可以使用 WHERE 子句轻松完成聚合 SQL。然而,这因两个挑战而变得复杂:

  1. target_date 不固定,但每个site_id 都不同
  2. 我希望在同一个表中输出多个日期范围;所以我不能做一个简单的WHERE 来排除超出event 表范围的记录。

我想到的一种解决方法是简单地进行多个查询,每个日期范围一个,然后使用视图将它们粘贴在一起。有没有更简单、更好或更优雅的方式来实现我的目标?

【问题讨论】:

  • 可能发布一些示例数据和预期输出。
  • 您的 Postgres 版本对于这个问题至关重要。

标签: sql postgresql aggregate-functions aggregate-filter


【解决方案1】:

你会做这样的事情:

select sum(case when target_date - event_date < 30 then 1 else 0 end) as within_030,
       sum(case when target_date - event_date < 60 then 1 else 0 end) as within_060,
       sum(case when target_date - event_date < 90 then 1 else 0 end) as within_090    
from event e join
     site s
     on e.site_id = s.site_id;

也就是说,您可以使用条件聚合。我不确定“60 天内”是什么意思。这给出了目标日期前的几天,但类似的逻辑可以满足您的需要。

【讨论】:

    【解决方案2】:

    在 Postgres 9.4 中使用 new aggregate FILTER clause:

    假设实际的 date 数据类型,所以我们可以简单地加/减 integer 数天。
    将“n 天内”解释为“+/- n 天”:

    SELECT site_id, s.target_date
         , sum(e.num_events) FILTER (WHERE e.event_date BETWEEN s.target_date - 30
                                                 AND s.target_date + 30) AS sum_30
         , sum(e.num_events) FILTER (WHERE e.event_date BETWEEN s.target_date - 60
                                                 AND s.target_date + 60) AS sum_60
         , sum(e.num_events) FILTER (WHERE e.event_date BETWEEN s.target_date - 90
                                                 AND s.target_date + 90) AS sum_90
    FROM   site  s
    JOIN   event e USING (site_id)
    WHERE   e.event_date BETWEEN s.target_date - 90
                             AND s.target_date + 90
    GROUP  BY 1, 2;
    

    还将条件添加为WHERE 子句以尽早排除不相关的行。如果在event 中的sum_90 范围之外的行数多于微不足道的行数,这应该会更快。

    【讨论】:

    • FILTER 与其他答案所建议的使用 CASE 相比有什么优势?
    • 它更干净、更快捷。差别不会很大,但用EXPLAIN ANALYZE 测试。这是 pg 9.4 中实现的 SQL 标准方式。
    • @SRobertJames:考虑添加的WHERE 条件。顺便说一句,这个答案也是正确,而不是当前接受的答案,将num_events替换为1
    猜你喜欢
    • 2020-12-25
    • 2018-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    相关资源
    最近更新 更多