我有一个具体的问题.我有一个包含无效值的表.我需要用0
大于的前一个值替换无效值(此处)0
.
困难在于,对我来说使用Update或插入是不合适的(Cursor和update会这样做).我唯一的方法是使用Select语句.
当我lag(col1, 1)
在大小写时使用- 函数时,我只得到一个具有正确值的列.
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
内容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
预期的查询结果:
--------------------------- 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
Lukas Eder.. 8
我假设一个额外的列col0
包含一个明显的数据排序标准,因为您的col1
示例数据并未真正正确排序(重复,尾随值为A
和E
).
我喜欢MODEL
这些用途的条款.以下查询产生预期结果:
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)])
)
结果:
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
虽然上面看起来很酷(或可怕,取决于你的观点),你当然应该更喜欢使用基于窗口函数的appraoch,LAST_VALUE() IGNORE NULLS
通过nop77svk(使用)或MT0(使用LAG() IGNORE NULLS
)的其他优雅答案公开.我在这篇博客文章中更详细地解释了这些答案.
我假设一个额外的列col0
包含一个明显的数据排序标准,因为您的col1
示例数据并未真正正确排序(重复,尾随值为A
和E
).
我喜欢MODEL
这些用途的条款.以下查询产生预期结果:
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)])
)
结果:
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
虽然上面看起来很酷(或可怕,取决于你的观点),你当然应该更喜欢使用基于窗口函数的appraoch,LAST_VALUE() IGNORE NULLS
通过nop77svk(使用)或MT0(使用LAG() IGNORE NULLS
)的其他优雅答案公开.我在这篇博客文章中更详细地解释了这些答案.
假设您希望按照原始数据顺序(无论可能是什么)获得先前的值,那么您的查询可能如下所示:
with preserve_the_order$ as ( select X.*, rownum as original_order$ from test_table X ) select X.col1, nvl(last_value(case when col2 > 0 then col2 end) ignore nulls over (order by original_order$ rows between unbounded preceding and current row), col2) as col2, nvl(last_value(case when col3 > 0 then col3 end) ignore nulls over (order by original_order$ rows between unbounded preceding and current row), col3) as col3, nvl(last_value(case when col4 > 0 then col4 end) ignore nulls over (order by original_order$ rows between unbounded preceding and current row), col4) as col4 from preserve_the_order$ X order by original_order$ ;
结果:
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 0 1 5 E 3 5 5