Jeg antager en ekstra kolonne col0
der indeholder et indlysende bestillingskriterie for dine data, som din col1
eksempeldata er ikke rigtig ordnet korrekt (gentagne, efterfølgende værdier af A
og E
).
Jeg elsker MODEL
klausul til den slags formål. Følgende forespørgsel giver det forventede resultat:
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)])
)
Resultat:
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
En note om MODEL-klausulen vs. vinduesfunktionsbaserede tilgange
Selvom ovenstående ser cool ud (eller skræmmende, afhængigt af dit synspunkt), bør du bestemt foretrække at bruge en vinduesfunktionsbaseret tilgang som afsløret af de andre elegante svar fra nop77svk (ved hjælp af LAST_VALUE() IGNORE NULLS
)
eller MT0 (ved hjælp af LAG() IGNORE NULLS
)
. Jeg har forklaret disse svar mere detaljeret i dette blogindlæg
.