使用上一个非空数量填充空值 - Oracle SQL

时间:2014-11-17 16:30:27

标签: sql oracle

我有一个包含4列的表:Item,Year,Month,Amount。 Amount的某些值为null,当发生这种情况时,我想用前一个非空值Amount值填充这些值。当只有一个空值时,我可以使用LAG函数轻松完成此操作,但当连续存在多个时,我不确定如何处理它。下面是一个示例,表示我想在查询中添加的列添加了一列:

Item | Year | Month | Amount | New_Amount
AAA  | 2013 | 01    | 100    | 100
AAA  | 2013 | 02    |        | 100
AAA  | 2013 | 03    | 150    | 150
AAA  | 2013 | 04    | 125    | 125
AAA  | 2013 | 05    |        | 125
AAA  | 2013 | 06    |        | 125
AAA  | 2013 | 07    |        | 125
AAA  | 2013 | 08    | 175    | 175

我有两个想法,我似乎无法开始工作以产生我想要的东西。首先我打算使用LAG,但后来我注意到当一行中有多个空值时,它不会满足。接下来我将使用FIRST_VALUE,但是在这种情况下,如果有一个null后跟值后跟更多的空值,那将无济于事。有没有办法使用FIRST_VALUE或其他类似函数来检索最后一个非空值?

4 个答案:

答案 0 :(得分:9)

使用IGNORE NULLS

last_value 在Oracle 10g中运行良好:

select item, year, month, amount, 
       last_value(amount ignore nulls) 
         over(partition by item 
              order by year, month 
              rows between unbounded preceding and 1 preceding) from tab;

rows between unbounded preceding and 1 preceding设置分析函数的窗口。

在这种情况下,Oracle正在从开始(UNBOUNDED PRECEDING)的PARTITION BY(同一项)中定义的组内搜索LAST_VALUE,直到当前行 - 1(1 PRECEDING)

它是Oracle 10g中IGNORE NULLS的LEAD / LAG的常见替代品

但是,如果您正在使用Oracle 11g,您可以使用Gordon Linoff的答案中的LAG(有一个小错误"忽略空值")

答案 1 :(得分:7)

这是一种方法。计算给定行之前的非空值的数量。然后将其用作窗口函数的组:

select t.item, t.year, t.month, t.amount,
       max(t.amount) over (partition by t.item, grp) as new_amount
from (select t.*,
             count(Amount) over (Partition by item order by year, month) as grp
      from table t
     ) t;

在Oracle 11+版中,您可以ignore nulls使用lag()lead()

select t.item, t.year, t.month, t.amount,
       lag(t.amount ignore nulls) over (partition by t.item order by year, month) as new_amount
from table t

答案 2 :(得分:0)

答案非常糟糕:

Item | Year | Month | Amount | New_Amount
AAA  | 2013 | 01    | 100    | null
AAA  | 2013 | 02    |        | 100
AAA  | 2013 | 03    | 150    | 100
AAA  | 2013 | 04    | 125    | 150
AAA  | 2013 | 05    |        | 125
AAA  | 2013 | 06    |        | 125
AAA  | 2013 | 07    |        | 125
AAA  | 2013 | 08    | 175    | 125

是一个非常糟糕的结果:)

-

select item, year, month, amount, 
  last_value(amount ignore nulls) 
over(partition by item
  order by year, month
  rows between unbounded preceding and CURRENT ROW) from tab;

更好

答案 3 :(得分:0)

以防万一,您正在使用其他数据库(例如sqlite),并且它没有忽略null功能。我在这里发布了另一个解决方案,供您参考。

  1. 您需要使用0/1列来表示Null / Non-Null数据
  2. 然后在步骤1中创建累积汇总列以计算指标编号。 -现在您可以看到数据已经看起来像按您的non_Null数据分组了。
  3. 最后一步,请使用一个Max函数组(在步骤2中)按累加总和将数据(此处为amont)填充为空项目。

附上图片以帮助您理解。 enter image description here