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