例の値が示すようにケースが単純な場合は、@Giorgosの回答 うまく機能します。
ただし、通常はそうではありません 。 id
の場合 列はserial
です 、time
が早い行という仮定に頼ることはできません。 id
も小さくなります 。
また、time
値(またはtimestamp
おそらくお持ちのように)簡単に重複する可能性があるため、並べ替え順序を明確にする必要があります。
両方が発生する可能性があり、id
が必要であると仮定します time
が最も早い行から タイムスライスごと(実際には、最小 id
最も早い時間 、同点の可能性があります)、このクエリは状況を適切に処理します:
SELECT *
FROM (
SELECT DISTINCT ON (way, grp)
id, way, time AS time_from
, max(time) OVER (PARTITION BY way, grp) AS time_to
FROM (
SELECT *
, row_number() OVER (ORDER BY time, id) -- id as tie breaker
- row_number() OVER (PARTITION BY way ORDER BY time, id) AS grp
FROM table1
) t
ORDER BY way, grp, time, id
) sub
ORDER BY time_from, id;
-
ORDER BY time, id
明確にすること。時間はではないと仮定します 一意の場合、(一意と想定される)id
を追加します 任意の結果を回避するため-卑劣な方法でクエリ間で変更される可能性があります。 -
max(time) OVER (PARTITION BY way, grp)
:ORDER BY
なし 、ウィンドウフレームはPARTITIONのすべての行にまたがるので、タイムスライスごとの絶対最大値を取得します。 -
外側のクエリレイヤーは、別の
ORDER BY
にバインドされているため、結果に目的の並べ替え順序を生成するためにのみ必要です。 サブクエリsub
DISTINCT ON
を使用する 。詳細:
SQLフィドル ユースケースのデモンストレーション。
パフォーマンスを最適化する場合は、plpgsql関数の方が高速である可能性があります。密接に関連する答え:
余談ですが、基本的なタイプ名time
は使用しないでください 識別子として(標準SQLで予約されている単語> 。