sql >> データベース >  >> RDS >> PostgreSQL

次の行を一意でない値でグループ化する方法

    例の値が示すようにケースが単純な場合は、@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で予約されている単語> 。



    1. PHPを使用して非アクティブなユーザーをログアウトします

    2. doubleデータ型にNULL値を挿入するMySQLPython

    3. MySQLのユーザー名とパスワードを逆コンパイルから保護するにはどうすればよいですか?

    4. SequelizeのfindAll()が取得されない