FIRST_VALUE函数未按预期工作

时间:2014-01-09 06:09:23

标签: sql oracle analytic-functions

我以为我理解它是如何运作的,但现在我很困惑。

我有一个数据集:

id date     value
1  20080101 null
2  20090101 34
3  20100101 null

从2008年1月,2009年和2010年开始的三条记录。现在我想创建一个具有最新非null值的新列“value2”。基本上我想要一个3个34s的value2列。我写道:

select id, date, value, first_value(value) ignore nulls over (order by date desc) as value2 from table

然而,我得到了:

id date     value   value2
1  20080101 null    34
2  20090101 34      34
3  20100101 null    null

最后一个值仍为空而不是34.这里出了什么问题?

3 个答案:

答案 0 :(得分:1)

分析函数的默认窗口为ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,如果您将其更改为ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,那么您将获得所需的结果:

查询1

WITH table_name AS (
            SELECT 1 AS id, TO_DATE( '20080101', 'YYYYMMDD' ) AS "date", NULL AS value FROM DUAL
  UNION ALL SELECT 2, TO_DATE( '20090101', 'YYYYMMDD' ), 34   FROM DUAL
  UNION ALL SELECT 3, TO_DATE( '20100101', 'YYYYMMDD' ), NULL FROM DUAL
)
SELECT id,
       "date",
       value,
       FIRST_VALUE( value IGNORE NULLS ) OVER (ORDER BY "date" DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS value2
FROM   table_name;

<强>结果

ID  | date                   | VALUE   | VALUE2
-------------------------------------------------
3   | 2010-01-01 00:00:00    | (null)  | 34
2   | 2009-01-01 00:00:00    | 34      | 34
1   | 2008-01-01 00:00:00    | (null)  | 34

答案 1 :(得分:0)

尝试删除order by子句

中的空值

可能的解决方案可能是

with x as (
    select 1  as id , 20080101 as ddate , null as v from dual union all 
    select 2 , 20090101 ,34 from dual union all 
    select 3 , 20100101 ,null from dual union all 
    select 4 , 20090101 ,15 from dual union all 
    select 5 , 20110101 ,null from dual union all 
    select 6 , 20120101 ,null from dual union all 
    select 7 , 20030101 ,55 from dual
) 
select  x.* , 
    first_value(v) over (order by case when v is null then null else ddate end) as last_nn_v
from    x
order by ddate
/

        ID      DDATE          V  LAST_NN_V
---------- ---------- ---------- ----------
         7   20030101         55         55
         1   20080101                    55
         4   20090101         15         55
         2   20090101         34         55
         3   20100101                    55
         5   20110101                    55
         6   20120101                    55

答案 2 :(得分:0)

你忘记了窗户。默认值是UNBOUNDED PRECEDING和CURRENT ROW之间的范围,意味着您的值正在从第一行到当前行的窗口中查找。您的排序行是:

id date     value
3  20100101 null
2  20090101 34
1  20080101 null
  • 对于id 1,记录3,2,1是焦点。值34位于第二行。
  • 对于id 2,记录3,2是焦点。值34位于第二行。
  • 对于id 3,只有记录3处于焦点。因此无法找到值34。

BTW:你的请求中有一个拼写错误:它是first_value(值忽略空值),而不是first_value(value)忽略空值。