Avec des ensembles de données plus volumineux, les fonctions de fenêtre sont le moyen le plus efficace d'effectuer ce type de requêtes :la table ne sera analysée qu'une seule fois, au lieu d'une fois pour chaque date, comme le ferait une auto-jointure. Cela semble aussi beaucoup plus simple. :) PostgreSQL 8.4 et versions ultérieures prennent en charge les fonctions de fenêtre.
Voici à quoi cela ressemble :
SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM subscriptions
GROUP BY created_at;
Ici OVER
crée la fenêtre ; ORDER BY created_at
signifie qu'il doit résumer les comptes dans created_at
commande.
Modifier : Si vous souhaitez supprimer les e-mails en double en une seule journée, vous pouvez utiliser sum(count(distinct email))
. Malheureusement, cela ne supprimera pas les doublons qui traversent des dates différentes.
Si vous souhaitez supprimer tous doublons, je pense que le plus simple est d'utiliser une sous-requête et DISTINCT ON
. Cela attribuera les e-mails à leur date la plus ancienne (car je trie par created_at dans l'ordre croissant, il choisira le plus ancien) :
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;
Si vous créez un index sur (email, created_at)
, cette requête ne devrait pas non plus être trop lente.
(Si vous voulez tester, voici comment j'ai créé l'exemple de jeu de données)
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);