При больших наборах данных оконные функции являются наиболее эффективным способом выполнения таких запросов - таблица будет сканироваться только один раз, а не один раз для каждой даты, например самостоятельное соединение будет делать. Это также выглядит намного проще. :) 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
. Это будет приписывать электронные письма к их самой ранней дате (поскольку я сортирую по созданному в порядке возрастания, он выберет самую раннюю):
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);