I have a specific problem. I have a table which contains invalid values.
I need to replace the invalid values (here 0
) with the previous value which is bigger than 0
.
The difficulty is, it is not appropiate for me to use an Update or an insert(Cursor and update would do it).Well my only way is to use a Select statement.
When I use the lag(col1, 1)
- function with when case, I get only one column with the correct value.
select col1, col2 realcol2,
(case
when col2 = 0 then
lag(col2,1,1) over (partition by col1 order by col1 )
else
col2
end ) col2,
col3 realcol3,
(case
when col3 = 0 then
lag(col3,1,1) over (partition by col1 order by col1 )
else
col3
end ) col3
from test_table
Contents of TEST_TABLE
:
---------------------------
Col1 | Col2 | Col3 | Col4
---------------------------
A | 0 | 1 | 5
B | 0 | 4 | 0
C | 2 | 0 | 0
D | 0 | 0 | 0
E | 3 | 5 | 0
F | 0 | 3 | 0
G | 0 | 3 | 1
A | 0 | 1 | 5
E | 3 | 5 | 0
Expected query result:
---------------------------
Col1 | Col2 | Col3 | Col4
---------------------------
A | 0 | 1 | 5
B | 0 | 4 | 5
C | 2 | 4 | 5
D | 2 | 4 | 5
E | 3 | 5 | 5
F | 3 | 3 | 5
G | 3 | 3 | 1
A | 3 | 1 | 5
E | 3 | 5 | 5
I'm assuming an additional column
col0
that contains an obvious ordering criteria for your data, as yourcol1
example data isn't really ordered correctly (repeated, trailing values ofA
andE
).I love the
MODEL
clause for these kinds of purposes. The following query yields the expected result:Result:
SQLFiddle
A note on the MODEL clause vs. window function-based approaches
While the above looks cool (or scary, depending on your point of view), you should certainly prefer using a window function based appraoch as exposed by the other elegant answers by nop77svk (using
LAST_VALUE() IGNORE NULLS
) or MT0 (usingLAG() IGNORE NULLS
). I've explained these answers more in detail in this blog post.Result:
Assuming you want the previous values as per your original data order (whatever that might be), then your query might look like:
Result: