对于较大的数据集,window functions 是执行此类查询的最有效方式 - 表将仅被扫描一次,而不是像自联接那样每个日期扫描一次。它看起来也简单了很多。 :) PostgreSQL 8.4 及更高版本支持窗口函数。
这就是它的样子:
SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM subscriptions
GROUP BY created_at;
这里OVER创建窗口; ORDER BY created_at 表示它必须以created_at 的顺序来汇总计数。
编辑:如果您想在一天内删除重复的电子邮件,您可以使用sum(count(distinct email))。不幸的是,这不会删除跨越不同日期的重复项。
如果你想删除 all 重复项,我认为最简单的方法是使用子查询和DISTINCT ON。这会将电子邮件归因于它们的最早日期(因为我按 created_at 升序排序,它会选择最早的):
SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM (
SELECT DISTINCT ON (email) created_at, email
FROM subscriptions ORDER BY email, created_at
) AS subq
GROUP BY created_at;
如果您在(email, created_at) 上创建索引,此查询也不应该太慢。
(如果你想测试,这就是我创建示例数据集的方式)
create table subscriptions as
select date '2000-04-04' + (i/10000)::int as created_at,
'foofoobar@foobar.com' || (i%700000)::text as email
from generate_series(1,1000000) i;
create index on subscriptions (email, created_at);