С по-големи набори от данни, прозоречни функции са най-ефективният начин за извършване на тези видове заявки - таблицата ще бъде сканирана само веднъж, вместо веднъж за всяка дата, както би направило самостоятелно присъединяване. Освен това изглежда много по-просто. :) 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);