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

Come utilizzare una struttura dati ad anello nelle funzioni finestra

  • Usa COALESCE come fornito da @Justin.
  • Con first_value() / last_value() di cui hai bisogno per aggiungere un ORDER BY clausola alla definizione della finestra o l'ordine è non definito . Sei stato fortunato nell'esempio, perché le righe sono in ordine subito dopo aver creato la tabella fittizia.
    Una volta aggiunto ORDER BY , la cornice della finestra predefinita termina nella riga corrente , e hai bisogno di un caso speciale last_value() call - o ripristina l'ordinamento nella cornice della finestra come mostrato nel mio primo esempio.

  • Quando riutilizzi una definizione di finestra più volte, un WINDOW esplicito la clausola semplifica molto la sintassi:

SELECT ring, part, ARRAY[
          coalesce(
             lag(part) OVER w
            ,first_value(part) OVER (PARTITION BY ring ORDER BY part DESC))
         ,part
         ,coalesce(
             lead(part) OVER w
            ,first_value(part) OVER w)
         ] AS neighbours
FROM   rp
WINDOW w AS (PARTITION BY ring ORDER BY part);

Meglio ancora , riutilizza la stessa definizione di finestra, così Postgres può calcolare tutti i valori in una singola scansione. Affinché ciò funzioni, dobbiamo definire una cornice della finestra personalizzata :

SELECT ring, part, ARRAY[
          coalesce(
             lag(part) OVER w
            ,last_value(part) OVER w)
         ,part
         ,coalesce(
             lead(part) OVER w
            ,first_value(part) OVER w)
         ] AS neighbours
FROM   rp
WINDOW w AS (PARTITION BY ring
             ORDER BY part
             RANGE BETWEEN UNBOUNDED PRECEDING
                       AND UNBOUNDED FOLLOWING)
ORDER  BY 1,2;

Puoi persino adattare la definizione del frame per ogni chiamata di funzione della finestra:

SELECT ring, part, ARRAY[
          coalesce(
             lag(part) OVER w
            ,last_value(part) OVER (w RANGE BETWEEN CURRENT ROW
                                                AND UNBOUNDED FOLLOWING))
         ,part
         ,coalesce(
             lead(part) OVER w
            ,first_value(part) OVER w)
         ] AS neighbours
FROM   rp
WINDOW w AS (PARTITION BY ring ORDER BY part)
ORDER  BY 1,2;

Potrebbe essere più veloce per anelli con molte parti. Dovrai fare un test.

SQL Fiddle dimostrando tutti e tre con un test case migliorato. Prendi in considerazione i piani di query.

Ulteriori informazioni sulle definizioni dei frame delle finestre:

  • Nel manuale.
  • Funzione finestra PostgreSQL:partizione per confronto
  • Query PostgreSQL con data massima e minima più ID associato per riga