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
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
.