计算由在另一个字段上定义的 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
子句。然而,这因两个挑战而变得复杂:
target_date
不固定,每个site_id
都不同
- 我希望在同一个日期范围内输出多个日期范围table;所以我不能做一个简单的
WHERE
来排除 event
table. 范围之外的记录
我想到的一个解决方法是简单地进行几个查询,每个日期范围一个,然后使用视图将它们粘贴在一起。有没有更简单、更好或更优雅的方法来实现我的目标?
你会做这样的事情:
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
范围之外的行数不多,这应该会快得多
我有 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
子句。然而,这因两个挑战而变得复杂:
target_date
不固定,每个site_id
都不同
- 我希望在同一个日期范围内输出多个日期范围table;所以我不能做一个简单的
WHERE
来排除event
table. 范围之外的记录
我想到的一个解决方法是简单地进行几个查询,每个日期范围一个,然后使用视图将它们粘贴在一起。有没有更简单、更好或更优雅的方法来实现我的目标?
你会做这样的事情:
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
范围之外的行数不多,这应该会快得多