有了更大的数据集,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))
。不幸的是,这不会删除跨越不同日期的重复。
如果你想删除所有重复,我认为最简单的是使用子查询和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,
'[email protected]' || (i%700000)::text as email
from generate_series(1,1000000) i;
create index on subscriptions (email, created_at);
这是很棒的intgr,只有我的订阅表包含大量重复的电子邮件行。所以'over'所做的是'count'数字,但是我仍然需要重新计算每个后续日期的唯一电子邮件。 – Khairul 2011-04-18 09:53:00
我用“DISTINCT ON”子查询更新了我的答案。它仍然比Andriy的答案快得多 - 可以在几秒钟内处理一百万行 - 但可能更复杂。 – intgr 2011-04-18 13:55:29
关于generate_series函数的不错提示! – 2011-04-19 06:33:48