Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle Lag-Funktion mit dynamischem Parameter

Ich gehe von einer zusätzlichen Spalte col0 aus die ein offensichtliches Ordnungskriterium für Ihre Daten enthält, wie Ihr col1 Beispieldaten sind nicht wirklich richtig geordnet (wiederholte, nachgestellte Werte von A und E ).

Ich liebe das MODEL Klausel für diese Art von Zwecken. Die folgende Abfrage liefert das erwartete Ergebnis:

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

Ergebnis:

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

Ein Hinweis zur MODEL-Klausel im Vergleich zu auf Fensterfunktionen basierenden Ansätzen

Während das Obige cool aussieht (oder beängstigend, je nach Sichtweise), sollten Sie auf jeden Fall einen auf Fensterfunktionen basierenden Ansatz bevorzugen, wie die anderen eleganten Antworten von nop77svk (unter Verwendung von LAST_VALUE() IGNORE NULLS). ) oder MT0 (unter Verwendung von LAG() IGNORE NULLS). ) . Ich habe diese Antworten in diesem Blogbeitrag ausführlicher erklärt .