PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come raggruppare le righe seguenti per valore non univoco

Se il tuo caso è semplice come suggeriscono i valori di esempio, Risposta di @Giorgos serve bene.

Tuttavia, solitamente non è così . Se l'id colonna è un serial , non puoi fare affidamento sul presupposto che una riga con un time precedente ha anche un id più piccolo .
Inoltre, time valori (o timestamp come probabilmente hai fatto) possono essere facilmente duplicati, è necessario rendere l'ordinamento univoco.

Supponendo che entrambi possano accadere e tu voglia l'id dalla riga con la prima time per intervallo di tempo (in realtà, il più piccolo id per la prima volta , potrebbero esserci dei legami), questa query tratterebbe la situazione in modo appropriato:

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 essere inequivocabile. Supponendo che il tempo non sia unico, aggiungi l'id (presunto univoco). per evitare risultati arbitrari, che potrebbero cambiare tra le query in modi subdoli.

  • max(time) OVER (PARTITION BY way, grp) :senza ORDER BY , il frame della finestra si estende su tutte le righe della PARTITION, quindi otteniamo il massimo assoluto per intervallo di tempo.

  • Il livello di query esterno è necessario solo per produrre l'ordinamento desiderato nel risultato, poiché siamo vincolati a un diverso ORDER BY nella sottoquery sub utilizzando DISTINCT ON . Dettagli:

SQL Fiddle dimostrando il caso d'uso.

Se stai cercando di ottimizzare le prestazioni, una funzione plpgsql potrebbe essere più veloce in questo caso. Risposta strettamente correlata:

A parte:non utilizzare il nome del tipo di base time come identificatore (anche una parola riservata in SQL standard ).