より大きなデータセットでは、ウィンドウ関数 これらの種類のクエリを実行する最も効率的な方法です。テーブルは、自己参加のように日付ごとに1回ではなく、1回だけスキャンされます。また、非常にシンプルに見えます。 :)PostgreSQL8.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
のカウントを合計する必要があることを意味します 注文します。
編集: 1日以内に重複するメールを削除する場合は、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);