2

次のようなデータ(「TimeStamp」でソート)があります。

      Key     |        TimeStamp        |   Column3   |   ColumnN
--------------+-------------------------+-------------+--------------
       1      |   2012-01-01 08:00:23   |     ...     |     ...
       2      |   2012-01-01 08:01:07   |     ...     |     ...
       3      |   2012-01-01 08:02:56   |     ...     |     ...
       6      |   2012-01-01 08:02:56   |     ...     |     ...
       4      |   2012-01-01 08:03:39   |     ...     |     ...
       5      |   2012-01-01 08:04:32   |     ...     |     ...

各レコードの「TimeStamp」の次の(次の行だけでなく)を選択する必要があります。

たとえば、上記のデータは次のようになります。

      Key     |          Begin          |           End           |   Column3   |   ColumnN
--------------+-------------------------+-------------------------+-------------+--------------
       1      |   2012-01-01 08:00:23   |   2012-01-01 08:01:07   |     ...     |     ...
       2      |   2012-01-01 08:01:07   |   2012-01-01 08:02:56   |     ...     |     ...
       3      |   2012-01-01 08:02:56   |   2012-01-01 08:03:39   |     ...     |     ...
       6      |   2012-01-01 08:02:56   |   2012-01-01 08:03:39   |     ...     |     ...
       4      |   2012-01-01 08:03:39   |   2012-01-01 08:04:32   |     ...     |     ...
       5      |   2012-01-01 08:04:32   |   NULL                  |     ...     |     ...

これにウィンドウ関数を使用しようとしましたが、この結果を得ることができませんでした。何かご意見は?

4

3 に答える 3

4

これは、相関サブクエリよりもはるかに高速です。

WITH x AS (
   SELECT *, dense_rank() OVER (ORDER BY ts) AS rnk
   FROM   tbl
   )
SELECT x.key, x.ts AS ts_begin, y.ts As ts_end
FROM   x
LEFT   JOIN (SELECT DISTINCT ts, rnk FROM x) y ON y.rnk = (x.rnk + 1)
ORDER  BY x.ts

->sqlfiddle

  • ウィンドウ関数dense_rank()を使用して、CTEにギャップのないランキングを取得します。
  • 次に、 「次の」タイムスタンプ (および 1 つだけ) を取得するために、オフセットによるそれ自体LEFT JOINのバージョンへの結果。DISTINCT1
  • または、 forGROUP BY 1,2の代わりに使用することもできます。並べ替え順序がウィンドウ関数と一致するため、ここではより高速になると予想されます。しかし、チェックして、自分の目で確かめてください。DISTINCTyDISTINCTORDER BYEXPLAIN ANALYZE
于 2013-02-12T23:25:04.623 に答える
1

次のように subselect を使用して「次の」値を取得できます。

SELECT "Key", 
       t1.Timestamp as "Begin", 
       (SELECT min(t2."TimeStamp") 
        FROM the_table t2
        WHERE t2."TimeStamp" > t1."TimeStamp") as "End",
       column3, ...
FROM the_table t1

ただし、このクエリは遅くなる可能性があります。高速にする必要がある場合は、単純な PL/SQL 関数を記述してください。

于 2013-02-12T23:00:55.617 に答える