Oracle
 sql >> Base de données >  >> RDS >> Oracle

Fonction Oracle Lag avec paramètre dynamique

Je suppose une colonne supplémentaire col0 qui contient un critère de classement évident pour vos données, comme votre col1 les données d'exemple ne sont pas vraiment ordonnées correctement (valeurs répétées et de fin de A et E ).

J'adore le MODEL clause à ces fins. La requête suivante donne le résultat attendu :

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

Résultat :

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

Une note sur la clause MODEL par rapport aux approches basées sur la fonction de fenêtre

Bien que ce qui précède semble cool (ou effrayant, selon votre point de vue), vous devriez certainement préférer utiliser une approche basée sur la fonction de fenêtre comme exposé par les autres réponses élégantes de nop77svk (en utilisant LAST_VALUE() IGNORE NULLS ) ou MT0 (en utilisant LAG() IGNORE NULLS ) . J'ai expliqué ces réponses plus en détail dans cet article de blog .