sql >> Base de Datos >  >> RDS >> Oracle

Función Oracle Lag con parámetro dinámico

Estoy asumiendo una columna adicional col0 que contiene un criterio de ordenación obvio para sus datos, como su col1 los datos de ejemplo no están realmente ordenados correctamente (valores finales repetidos de A y E ).

Me encanta el MODEL cláusula para este tipo de propósitos. La siguiente consulta arroja el resultado esperado:

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)])
  )

Resultado:

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 sobre la cláusula MODEL frente a los enfoques basados ​​en funciones de ventana

Si bien lo anterior parece genial (o aterrador, según su punto de vista), ciertamente debería preferir usar un enfoque basado en la función de ventana como lo exponen las otras respuestas elegantes de nop77svk (usando LAST_VALUE() IGNORE NULLS ) o MT0 (usando LAG() IGNORE NULLS ) . Expliqué estas respuestas más detalladamente en esta publicación de blog .