私はmysqlタグを見逃し、この解決策を書きました。残念ながら、ウィンドウ関数をサポートしていないため、これはMySQLでは機能しません 。
とにかく投稿しますので、少し力を入れています。 PostgreSQLでテスト済み。 OracleまたはSQLServer(またはウィンドウ関数をサポートするその他の適切なRDBMS)でも同様に機能します。
テストセットアップ
CREATE TEMP TABLE v(id int, visit date);
INSERT INTO v VALUES
(444631, '2011-11-07')
,(444631, '2011-11-06')
,(444631, '2011-11-05')
,(444631, '2011-11-04')
,(444631, '2011-11-02')
,(444631, '2011-11-01')
,(444632, '2011-12-02')
,(444632, '2011-12-03')
,(444632, '2011-12-05');
シンプルバージョン
-- add 1 to "difference" to get number of days of the longest period
SELECT id, max(dur) + 1 as max_consecutive_days
FROM (
-- calculate date difference of min and max in the group
SELECT id, grp, max(visit) - min(visit) as dur
FROM (
-- consecutive days end up in a group
SELECT *, sum(step) OVER (ORDER BY id, rn) AS grp
FROM (
-- step up at the start of a new group of days
SELECT id
,row_number() OVER w AS rn
,visit
,CASE WHEN COALESCE(visit - lag(visit) OVER w, 1) = 1
THEN 0 ELSE 1 END AS step
FROM v
WINDOW w AS (PARTITION BY id ORDER BY visit)
ORDER BY 1,2
) x
) y
GROUP BY 1,2
) z
GROUP BY 1
ORDER BY 1
LIMIT 1;
出力:
id | max_consecutive_days
--------+----------------------
444631 | 4
速い/短い
私は後でさらに良い方法を見つけました。 grp
数値は連続的ではありません(ただし、連続的に増加します)。これらは目的を達成するための手段にすぎないため、問題ではありません。
SELECT id, max(dur) + 1 AS max_consecutive_days
FROM (
SELECT id, grp, max(visit) - min(visit) AS dur
FROM (
-- subtract an integer representing the number of day from the row_number()
-- creates a "group number" (grp) for consecutive days
SELECT id
,EXTRACT(epoch from visit)::int / 86400
- row_number() OVER (PARTITION BY id ORDER BY visit) AS grp
,visit
FROM v
ORDER BY 1,2
) x
GROUP BY 1,2
) y
GROUP BY 1
ORDER BY 1
LIMIT 1;
その他
- A 手続き型ソリューション
同様の問題の場合。
MySQLで同様の何かを実装できる可能性があります 。 - 詳細な説明を含むdba.SEに関する密接に関連する回答
ここ および こちら 。 - そしてSO:
GROUPBYおよび連続する数値の集計