查询如下:
with t
as (
select 450 id, null txt , 3488 id_usr from dual union all
select 449 , null , 3488 from dual union all
select 79 , 'A' , 3488 from dual union all
select 78 , 'X' , 3488 from dual
)
select id
, txt
, id_usr
, first_value(txt ignore nulls) over (partition by id_usr order by id desc) first_one
from t
Run Code Online (Sandbox Code Playgroud)
并返回:
ID TXT D_USR FIRST_ONE
450 3488
449 3488
79 A 3488 A
78 X 3488 A
Run Code Online (Sandbox Code Playgroud)
这是预期的:
ID TXT ID_USR FIRST_ONE
450 3488 A
449 3488 A
79 A 3488 A
78 X 3488 A
Run Code Online (Sandbox Code Playgroud)
怎么了?为什么?
默认RANGE / ROWS为FIRST_VALUE(作为任何其它分析功能)是BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
如果添加IGNORE NULLS,则NULL在构建范围时不会考虑值.
该RANGE变BETWEEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCEPT FOR THE NULL ROWS(这不是一个有效的OVER条款).
因为你txt的那些是NULL高id的,所以首先选择它们,并且它们的范围是空的,因为它们之间没有非NULL行和UNBOUNDED PRECEDING
您应该更改查询的任一ORDER BY或RANGE子句.
更改ORDER BY将具有NULLid的行放入窗口的末尾,以便NULL始终首先选择非值(如果有),并且RANGE保证将从该值开始:
with t
as (
select 450 id, null txt , 3488 id_usr from dual union all
select 449 , null , 3488 from dual union all
select 79 , 'A' , 3488 from dual union all
select 78 , 'X' , 3488 from dual
)
select id
, txt
, id_usr
, first_value(txt) over (partition by id_usr order by NVL2(TXT, NULL, id) DESC) first_one
from t
Run Code Online (Sandbox Code Playgroud)
更改重RANGE定义范围以包括NULL分区中的所有非行:
with t
as (
select 450 id, null txt , 3488 id_usr from dual union all
select 449 , null , 3488 from dual union all
select 79 , 'A' , 3488 from dual union all
select 78 , 'X' , 3488 from dual
)
select id
, txt
, id_usr
, first_value(txt IGNORE NULLS) over (partition by id_usr order by id DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) first_one
from t
Run Code Online (Sandbox Code Playgroud)