W przypadku większych zbiorów danych funkcje okien są najskuteczniejszym sposobem wykonywania tego rodzaju zapytań — tabela zostanie przeskanowana tylko raz, a nie raz dla każdej daty, jak w przypadku samodzielnego łączenia. Wygląda też na o wiele prostsze. :) PostgreSQL 8.4 i nowsze obsługują funkcje okien.
Tak to wygląda:
SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM subscriptions
GROUP BY created_at;
Tutaj OVER
tworzy okno; ORDER BY created_at
oznacza, że musi zsumować zliczenia w created_at
zamówienie.
Edytuj: Jeśli chcesz usunąć zduplikowane wiadomości e-mail w ciągu jednego dnia, możesz użyć sum(count(distinct email))
. Niestety nie spowoduje to usunięcia duplikatów, które przecinają różne daty.
Jeśli chcesz usunąć wszystkie duplikaty, myślę, że najłatwiej jest użyć podzapytania i DISTINCT ON
. Spowoduje to przypisanie e-maili do ich najwcześniejszej daty (ponieważ sortuję według created_at w kolejności rosnącej, wybierze najwcześniejszą):
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;
Jeśli utworzysz indeks na (email, created_at)
, to zapytanie również nie powinno być zbyt wolne.
(Jeśli chcesz przetestować, oto jak stworzyłem przykładowy zestaw danych)
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);