Oracle
 sql >> Database >  >> RDS >> Oracle

Funzione Oracle Lag con parametro dinamico

Sto assumendo una colonna aggiuntiva col0 che contiene un criterio di ordinamento ovvio per i tuoi dati, come il tuo col1 i dati di esempio non sono realmente ordinati correttamente (valori finali ripetuti di A e E ).

Adoro il MODEL clausola per questo tipo di scopi. La query seguente restituisce il risultato previsto:

WITH t(col0, col1, col2, col3, col4) AS (
  SELECT 1, 'A', 0, 1, 5 FROM DUAL UNION ALL
  SELECT 2, 'B', 0, 4, 0 FROM DUAL UNION ALL
  SELECT 3, 'C', 2, 0, 0 FROM DUAL UNION ALL
  SELECT 4, 'D', 0, 0, 0 FROM DUAL UNION ALL
  SELECT 5, 'E', 3, 5, 0 FROM DUAL UNION ALL
  SELECT 6, 'F', 0, 3, 0 FROM DUAL UNION ALL
  SELECT 7, 'G', 0, 3, 1 FROM DUAL UNION ALL
  SELECT 8, 'A', 0, 1, 5 FROM DUAL UNION ALL
  SELECT 9, 'E', 3, 5, 0 FROM DUAL
)
SELECT * FROM t
MODEL
  DIMENSION BY (row_number() OVER (ORDER BY col0) rn)
  MEASURES (col1, col2, col3, col4)
  RULES (
    col2[any] = DECODE(col2[cv(rn)], 0, NVL(col2[cv(rn) - 1], 0), col2[cv(rn)]),
    col3[any] = DECODE(col3[cv(rn)], 0, NVL(col3[cv(rn) - 1], 0), col3[cv(rn)]),
    col4[any] = DECODE(col4[cv(rn)], 0, NVL(col4[cv(rn) - 1], 0), col4[cv(rn)])
  )

Risultato:

RN   COL1  COL2  COL3  COL4
1    A     0     1     5
2    B     0     4     5
3    C     2     4     5
4    D     2     4     5
5    E     3     5     5
6    F     3     3     5
7    G     3     3     1
8    A     3     1     5
9    E     3     5     5

SQLFiddle

Una nota sulla clausola MODEL rispetto agli approcci basati sulla funzione della finestra

Mentre quanto sopra sembra interessante (o spaventoso, a seconda del tuo punto di vista), dovresti sicuramente preferire l'uso di un approccio basato sulla funzione della finestra come esposto dalle altre eleganti risposte di nop77svk (usando LAST_VALUE() IGNORE NULLS ) o MT0 (usando LAG() IGNORE NULLS ) . Ho spiegato queste risposte più in dettaglio in questo post del blog .