例の値が示すようにケースが単純な場合は、@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にバインドされているため、結果に目的の並べ替え順序を生成するためにのみ必要です。 サブクエリsubDISTINCT ONを使用する 。詳細:
SQLフィドル ユースケースのデモンストレーション。
パフォーマンスを最適化する場合は、plpgsql関数の方が高速である可能性があります。密接に関連する答え:
余談ですが、基本的なタイプ名timeは使用しないでください 識別子として(標準SQLで予約されている単語> 。