PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So gruppieren Sie folgende Zeilen nach nicht eindeutigem Wert

Wenn Ihr Fall so einfach ist, wie die Beispielwerte vermuten lassen, Antwort von @Giorgos dient gut.

Dies ist jedoch normalerweise nicht der Fall . Wenn die id Spalte ist eine serial , können Sie sich nicht darauf verlassen, dass eine Zeile mit einer früheren time hat auch eine kleinere id .
Außerdem time Werte (oder timestamp wie Sie wahrscheinlich haben) können leicht Duplikate sein, Sie müssen die Sortierreihenfolge eindeutig machen.

Angenommen, beides kann passieren, und Sie möchten die id ab der Zeile mit der frühesten time pro Zeitscheibe (eigentlich die kleinste id zum frühesten Zeitpunkt , es könnte Unentschieden geben), würde diese Abfrage die Situation richtig behandeln:

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 eindeutig sein. Angenommen, Zeit ist nicht unique, fügen Sie die (angenommene eindeutige) id hinzu um willkürliche Ergebnisse zu vermeiden - die sich zwischen Abfragen auf hinterhältige Weise ändern könnten.

  • max(time) OVER (PARTITION BY way, grp) :ohne ORDER BY , der Fensterrahmen erstreckt sich über alle Zeilen der PARTITION, sodass wir das absolute Maximum pro Zeitscheibe erhalten.

  • Die äußere Abfrageschicht ist nur notwendig, um die gewünschte Sortierreihenfolge im Ergebnis zu erzeugen, da wir an einen anderen ORDER BY gebunden sind in der Unterabfrage sub durch Verwendung von DISTINCT ON . Einzelheiten:

SQL-Fiddle Demonstrieren des Anwendungsfalls.

Wenn Sie die Leistung optimieren möchten, könnte eine plpgsql-Funktion in einem solchen Fall schneller sein. Eng verwandte Antwort:

Übrigens:Verwenden Sie nicht den grundlegenden Typnamen time als Bezeichner (auch ein reserviertes Wort in Standard-SQL ).