Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Função Oracle Lag com parâmetro dinâmico


Estou assumindo uma coluna adicional col0 que contém um critério de ordenação óbvio para seus dados, como seu col1 os dados de exemplo não estão realmente ordenados corretamente (valores repetidos e à direita de A e E ).

Eu amo o MODEL cláusula para este tipo de fins. A consulta a seguir produz o 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

Uma observação sobre a cláusula MODEL versus abordagens baseadas em função de janela


Embora o acima pareça legal (ou assustador, dependendo do seu ponto de vista), você certamente deve preferir usar uma abordagem baseada em função de janela, conforme exposto pelas outras respostas elegantes de nop77svk (usando LAST_VALUE() IGNORE NULLS ) ou MT0 (usando LAG() IGNORE NULLS ) . Expliquei essas respostas com mais detalhes nesta postagem do blog .