По умолчанию 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
, они выбираются первыми, а их диапазоны пусты, поскольку между ними и UNBOUNDED PRECEDING
нет строк, отличных от NULL
.
Вы должны изменить либо ORDER BY
, либо RANGE
предложение вашего запроса.
Изменение ORDER BY
помещает строки с NULL
идентификаторами в конец окна, так что сначала будет всегда выбрано не 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
Изменение 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