The query is the following:
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
And returns:
ID TXT D_USR FIRST_ONE
450 3488
449 3488
79 A 3488 A
78 X 3488 A
This was the expected:
ID TXT ID_USR FIRST_ONE
450 3488 A
449 3488 A
79 A 3488 A
78 X 3488 A
What’s wrong and why?
Default
RANGE / ROWSforFIRST_VALUE(as for any other analytical function) isBETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.If you add
IGNORE NULLS, thenNULLvalues are not taken into account when building the range.The
RANGEbecomesBETWEEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCEPT FOR THE NULL ROWS(it’s not a validOVERclause).Since your
txt‘s that areNULLhave highid‘s, they are selected first, and their ranges are empty, since there are no non-NULLrows between them andUNBOUNDED PRECEDINGYou should change either
ORDER BYorRANGEclause of your query.Changing
ORDER BYputs the rows withNULLid’s to the end of the window so that a non-NULLvalue (if any) will be always selected first, and theRANGEwill guaranteedly start from that value:Changing
RANGEredefines range to include all non-NULLrows in the partition: