计算由在另一个字段上定义的 window 过滤的字段的总和

Calculate the sum of a field filtered by a window defined on another field

我有 table event:

event_date,
num_events,
site_id

我可以轻松地使用聚合 SQL 来完成 SELECT SUM(num_events) GROUP BY site_id

不过我还有一个table site:

site_id,
target_date

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

  1. target_date不固定,每个site_id
  2. 都不同
  3. 我希望在同一个日期范围内输出多个日期范围table;所以我不能做一个简单的 WHERE 来排除 event table.
  4. 范围之外的记录

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

你会做这样的事情:

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;

也就是可以使用条件聚合。我不确定 "within 60" 天是什么意思。这比目标日期早了几天,但类似的逻辑可以满足您的需要。

在 Postgres 9.4 中使用 new aggregate FILTER clause:

假设实际 date 数据类型,所以我们可以简单地加/减 integer 天数。
将 "within n days" 解释为“+/- 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 范围之外的行数不多,这应该会快得多