当前位置:  开发笔记 > 数据库 > 正文

具有动态参数的Oracle Lag函数

如何解决《具有动态参数的OracleLag函数》经验,为你挑选了2个好方法。

我有一个具体的问题.我有一个包含无效值的表.我需要用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示例数据并未真正正确排序(重复,尾随值为AE).

我喜欢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

关于MODEL子句与基于窗口函数的方法的注释

虽然上面看起来很酷(或可怕,取决于你的观点),你当然应该更喜欢使用基于窗口函数的appraoch,LAST_VALUE() IGNORE NULLS通过nop77svk(使用)或MT0(使用LAG() IGNORE NULLS)的其他优雅答案公开.我在这篇博客文章中更详细地解释了这些答案.



1> Lukas Eder..:

我假设一个额外的列col0包含一个明显的数据排序标准,因为您的col1示例数据并未真正正确排序(重复,尾随值为AE).

我喜欢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

关于MODEL子句与基于窗口函数的方法的注释

虽然上面看起来很酷(或可怕,取决于你的观点),你当然应该更喜欢使用基于窗口函数的appraoch,LAST_VALUE() IGNORE NULLS通过nop77svk(使用)或MT0(使用LAG() IGNORE NULLS)的其他优雅答案公开.我在这篇博客文章中更详细地解释了这些答案.



2> nop77svk..:

假设您希望按照原始数据顺序(无论可能是什么)获得先前的值,那么您的查询可能如下所示:

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

推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有