Ik ga uit van een extra kolom col0
die een voor de hand liggend bestelcriterium voor uw gegevens bevat, zoals uw col1
voorbeeldgegevens zijn niet echt correct geordend (herhaalde, volgwaarden van A
en E
).
Ik ben dol op het MODEL
clausule voor dit soort doeleinden. De volgende zoekopdracht levert het verwachte resultaat op:
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)])
)
Resultaat:
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
Een opmerking over de MODEL-clausule versus op vensterfunctie gebaseerde benaderingen
Hoewel het bovenstaande er cool uitziet (of eng, afhankelijk van je standpunt), zou je zeker de voorkeur moeten geven aan het gebruik van een op vensterfunctie gebaseerde benadering, zoals blijkt uit de andere elegante antwoorden van nop77svk (met LAST_VALUE() IGNORE NULLS
)
of MT0 (met LAG() IGNORE NULLS
)
. Ik heb deze antwoorden meer in detail uitgelegd in deze blogpost
.