このテーブルに基づいて構築します(SQLキーワード"date"を使用しません 列名として。):
CREATE TABLE tbl(
pid int
, the_date date
, PRIMARY KEY (pid, the_date)
);
クエリ:
SELECT pid, the_date
, row_number() OVER (PARTITION BY pid, grp ORDER BY the_date) AS in_streak
FROM (
SELECT *
, the_date - '2000-01-01'::date
- row_number() OVER (PARTITION BY pid ORDER BY the_date) AS grp
FROM tbl
) sub
ORDER BY pid, the_date;
date
を引く 別のdate
から integer
を生成します 。連続した日を探しているので、次の行はすべて1つ大きくなります。 。 row_number()
を引くと それから、ストリーク全体が同じグループになります(grp
)pid
ごと 。そうすれば、グループごとの数を簡単に処理できます。
grp
は2つの減算で計算されますが、これが最も速いはずです。同様に高速な代替手段は次のとおりです。
the_date - row_number() OVER (PARTITION BY pid ORDER BY the_date) * interval '1d' AS grp
1つの乗算、1つの減算。文字列の連結とキャストはより高価です。 EXPLAIN ANALYZE
でテストする 。
pid
で分割することを忘れないでください さらに両方 手順を実行しないと、分離する必要のあるグループが誤って混ざってしまいます。
サブクエリを使用します。これは通常、CTE よりも高速であるためです。 。ここでは、単純なサブクエリで実行できなかったことは何もありません。
そして、あなたがそれについて言及したので:dense_rank()
明らかにではありません ここで必要です。基本的なrow_number()
仕事をします。