これが1つのアプローチです。
タイムスタンプ順にステータス行を取得することから始めます (インライン ビューは としてエイリアス化されますs)。次に、MySQL ユーザー変数を使用して、前の行の値を保持し、各行を処理します。
私たちが本当に探しているのは、一連の「ダウン」ステータスの直後に続く「アップ」ステータスです。そして、「up」ステータスの行が見つかった場合、本当に必要なのは、前の一連の「down」ステータスからの最も古いタイムスタンプです。
したがって、次のようなものが機能します。
SELECT d.start_down
     , d.ended_down
  FROM (SELECT @i := @i + 1 AS i
             , @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down
             , @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down
             , @status := s.status
         FROM (SELECT t.time
                    , t.status
                 FROM mydata t
                WHERE t.status IN ('up','down')
                ORDER BY t.time ASC, t.status ASC
              ) s
         JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i
      ) d
WHERE d.start_down IS NOT NULL
  AND d.ended_down IS NOT NULL
これは、表示する特定のデータ セットに対して機能します。
これが処理しないもの (返さないもの) は、まだ終了していない「ダウン」期間です。つまり、「アップ」ステータスが続かない一連の「ダウン」ステータスです。
行を順番に返すためのファイルソート操作を回避するには、 にカバリング インデックスが必要です(time,status)。このクエリは、一時 (MyISAM) テーブルを生成して、 としてエイリアス化されたインライン ビューを具体化しますd。
注:このクエリが何を行っているかを理解するには、最も外側のクエリを剥がして、エイリアスとしてインライン ビューのクエリだけを実行します(選択リストにd追加できます)。s.time
このクエリは、「アップ」または「ダウン」ステータスのすべての行を取得しています。「トリック」は、「ダウン」期間を終了する行のみに「開始」時間と「終了」時間の両方を割り当てる (ダウン期間をマークする) ことです。(つまり、「ダウン」ステータスの行に続く「アップ」ステータスの最初の行です。) これが実際の作業が行われる場所です。最も外側のクエリは、この結果セット内のすべての「余分な」行を除外するだけです (つまり、必要ありません。)
SELECT @i := @i + 1 AS i
     , @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down
     , @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down
     , @status := s.status
     , s.time
  FROM (SELECT t.time
             , t.status
          FROM mydata t
         WHERE t.status IN ('up','down')
         ORDER BY t.time ASC, t.status ASC
       ) s
  JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i
エイリアス化されたインラインビューの目的はs、タイムスタンプ値で並べ替えられた行を取得することです。これにより、それらを順番に処理できます。エイリアス化されたインライン ビューはそのままなiので、クエリの開始時にいくつかのユーザー変数を初期化できます。
Oracle または SQL Server で実行している場合は、"分析関数" または "ランキング関数" (それぞれ名前が付けられているとおり) を利用できます。 "。