これはギャップと島の問題であり、変数を使用して解決する別の方法を次に示します。
SELECT
MIN(a) AS series_start,
MAX(a) AS series_end,
MAX(a) - MIN(a) + 1 AS series_count
FROM (
SELECT
a,
@r := @r + 1 AS r
FROM
yourtable,
(SELECT @r := 0) AS x
ORDER BY
a
) s
GROUP BY
a - r
ORDER BY
a - r
;
これがその仕組みです。
サブクエリは、テーブルの行に行番号を割り当て、次の行セットを返します。
a r
-- --
1 1
2 2
3 3
5 4
6 5
7 6
9 7
10 8
11 9
12 10
この場合、r
行番号を格納する列はたまたまid
データ サンプルの列と一致しますが、一般に列にギャップがある可能性があると想定してid
いるため、ここでは使用できません。
r
メインクエリは、との差によって結果をグループ化しますa
: 連続する値の場合、常に同じになります:
a r a - r
-- -- -----
1 1 0
2 2 0
3 3 0
5 4 1
6 5 1
7 6 1
9 7 2
10 8 2
11 9 2
12 10 2
これにより、そのような行をグループ化できます。この時点で残っているのは、最小値、最大値、およびカウントを取得することだけです。これにより、次の出力が得られます。
series_start series_end series_count
------------ ---------- ------------
1 3 3
5 7 3
9 12 4
@sgeddes のスキーマを借用した、このクエリの SQL Fiddle デモンストレーションは、こちらにあります。
アップデート
数値変数は使用できないため (コメントによると)、三角形の自己結合を使用して行番号を割り当てることができますが、変数を使用するよりも効率が大幅に低下します。とにかく、これが変更されたバージョンです。太字で強調表示されている以前のクエリへの変更です。
選択する
MIN(a) AS series_start、
MAX(a) AS series_end,
MAX(a) - MIN(a) + 1 AS series_count
から (
選択する
data.a、
COUNT(*) AS r
から
あなたのテーブルASデータ
内部結合
yourtable AS タリー
オン
data.id >= 集計.id
グループ化
data.a
) 秒
グループ化
a - r
オーダーバイ
a - r
;
アプローチ自体は変更されていません。サブクエリはランク付けされた行セットを返し、それが以前と同じように処理されます。
変更されたクエリの SQL Fiddle デモは、こちらから入手できます。