この回答では、例のデータのように、日付の昇順で並べ替えると、「id」フィールドが行に連続して番号を付けると仮定します。 (そのような列が存在しない場合は作成できます)。
1) 隣接する「id」値でテーブルを結合します。これにより、隣接する行がペアになります。 「割り当て」フィールドが変更された行を選択します。結果を一時テーブルに保存し、実行中のインデックスも保持します。
SET @idx =0;CREATE TEMPORARY TABLE boundsSELECT (@idx :=@idx + 1) AS idx, a1.date AS prev_end, a2.date AS next_start, a1.allocation as allocationFROM 割り当て a1JOIN 割り当て a2ON (a2.id =a1.id + 1)WHERE a1.allocation !=a2.allocation;
プレ>これにより、各行に「前の期間の終わり」、「次の期間の開始」、および「前の期間の「割り当て」の値」を含むテーブルが得られます。
<前>+------+------------+------------+---------- --+| idx |前へ | next_start |割り当て |+------+------------+------------+------------+| 1 | 2012-01-01 | 2012-01-02 | 0 || 2 | 2012-01-02 | 2012-01-03 | 2 || 3 | 2012-01-05 | 2012-01-06 | 0 |+-----+------------+------------+------------+コード> プレ>
2) 各ピリオドの開始と終了が同じ行にある必要があるため、隣接する行を再度結合する必要があります。
<前>boundaries
のような 2 番目の一時テーブルを作成してこれを行います しかしidx
を持っています フィールド 1 より大きい:+------+------------+------------+| idx |前へ | next_start |+--------------------+------------+------------+| 2 | 2012-01-01 | 2012-01-02 || 3 | 2012-01-02 | 2012-01-03 || 4 | 2012-01-05 | 2012-01-06 |+------+------------+------------+コード> プレ>
idx
に参加しましょう フィールドに入力すると、答えが得られます:SELECT 境界 2.next_start AS 開始、boundary.prev_end AS 終了、allocationFROM 境界結合境界 2USING(idx);+------------+---------- --+------------+|開始 |終了 |割り当て |+------------+------------+------------+| 2012-01-02 | 2012-01-02 | 2 || 2012-01-03 | 2012-01-05 | 0 |+------------+------------+------------+コード> プレ>
** この回答は「内部」期間を正しく取得しますが、最初に割り当て =0、最後に割り当て =5 である 2 つの「エッジ」期間を見逃していることに注意してください。これらは
UNION
を使用して取り込むことができます 節はありませんが、複雑にすることなく核となるアイデアを提示したかったのです。