U větších datových sad funkce oken jsou nejefektivnějším způsobem, jak provádět tyto druhy dotazů – tabulka bude prohledána pouze jednou, namísto jednou pro každé datum, jako by to dělalo vlastní připojení. Také to vypadá mnohem jednodušeji. :) PostgreSQL 8.4 a vyšší mají podporu pro funkce okna.
Takhle to vypadá:
SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM subscriptions
GROUP BY created_at;
Zde OVER
vytvoří okno; ORDER BY created_at
znamená, že musí sečíst počty v created_at
objednávka.
Upravit: Pokud chcete odstranit duplicitní e-maily během jednoho dne, můžete použít sum(count(distinct email))
. Bohužel se tím neodstraní duplikáty, které překračují různá data.
Pokud chcete odstranit vše duplikáty, myslím, že nejjednodušší je použít poddotaz a DISTINCT ON
. Toto přiřadí e-maily k jejich nejstaršímu datu (protože je řadím vzestupně podle created_at, vybere se nejstarší):
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;
Pokud vytvoříte index na (email, created_at)
, ani tento dotaz by neměl být příliš pomalý.
(Pokud chcete testovat, takto jsem vytvořil ukázkovou datovou sadu)
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);