Oracle
 sql >> Base de données >  >> RDS >> Oracle

Quel est le problème avec cette requête FIRST_VALUE ?

RANGE / ROWS par défaut pour FIRST_VALUE (comme pour toute autre fonction analytique) est BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW .

Si vous ajoutez IGNORE NULLS , puis NULL les valeurs ne sont pas prises en compte lors de la construction de la plage.

La RANGE devient BETWEEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCEPT FOR THE NULL ROWS (ce n'est pas un OVER valide clause).

Depuis votre txt 's qui sont NULL avoir un id élevé 's, ils sont sélectionnés en premier et leurs plages sont vides, car il n'y a pas de non-NULL lignes entre eux et UNBOUNDED PRECEDING

Vous devez modifier soit ORDER BY ou RANGE clause de votre requête.

Changer ORDER BY met les lignes avec NULL id est à la fin de la fenêtre de sorte qu'un non-NULL la valeur (le cas échéant) sera toujours sélectionnée en premier, et la RANGE commencera à coup sûr à partir de cette valeur :

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

Modification de RANGE redéfinit la plage pour inclure tous les non-NULL lignes dans la partition :

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