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

Condition de jointure Oracle avec Top 1

Je ne sais toujours pas quel enregistrement, dans votre exemple, vous vouliez, alors laissez-moi vous donner quelques alternatives.

J'ai compris de votre énoncé de problème que vous voulez la dernière date d'entrée en vigueur de ceux disponibles. Puisqu'il y a des liens impliqués, vous ne pouvez pas utiliser max() (comme vous l'avez déjà dit), et row_number() est la voie à suivre :

with cte as (
  select
    addrid, effectdt, xpirdt,
    row_number() over (partition by addrid order by effectdt desc) as rn
  from addrdata
)
select
  addrid, effectdt, xpirdt
from cte
where rn = 1

La partie suivante était où vous m'avez perdu avec les nulls ... Si votre tri secondaire est par date d'expiration et que vous voulez qu'une valeur nulle l'emporte sur la dernière date d'expiration, alors vous commanderiez par la date d'expiration et mettez les nulls first :

with cte as (
  select
    addrid, effectdt, xpirdt,
    row_number() over 
        (partition by addrid order by effectdt desc, xpirdt nulls first) as rn
  from addrdata
)
select
  addrid, effectdt, xpirdt
from cte
where rn = 1

Ce qui signifie que cette ligne est la gagnante :

10948448    5/14/2015   <null>

Si, toutefois, vous vouliez que les valeurs nulles soient prises en compte uniquement s'il n'y a pas de date d'expiration, vous pouvez utiliser nulls last (ou omettez-le, car c'est la valeur par défaut) :

with cte as (
  select
    addrid, effectdt, xpirdt,
    row_number() over
        (partition by addrid order by effectdt desc, xpirdt nulls last) as rn
  from addrdata
)
select
  addrid, effectdt, xpirdt
from cte
where rn = 1

Cela signifie que ce type a gagné le prix :

10948448    5/14/2015   5/13/2015

Puisque cela utilise row_number() vous ne perdrez aucune ligne - chaque ligne est garantie d'avoir un numéro de ligne. C'est juste que s'il y a de vrais liens, alors c'est un tirage au sort pour savoir quelle ligne est choisie. Cependant, votre problème avec les dates d'expiration nulles ne devrait pas poser de problème avec cette approche.

-- modifier 13/02/16 --

Je pense que je commence pour comprendre votre problème, mais je ne suis pas sûr à 100%. J'ai incorporé des extraits de votre code avec la jointure gauche avec ma suggestion, et la nécessité d'avoir des dates d'expiration nulles en premier, et c'est mon prochain crack :

with cte as (
  select
    addrid, effectdt, xpirdt,
    row_number() over 
        (partition by addrid order by effectdt desc, xpirdt nulls first) as rn
  from addrdata
)
select
  cte.addrid, effectdt, xpirdt
from
  mbr_person mb
  left join partyxref px on
    mb.nameid = px.nameid and
    px.reftype = 'COMM'
  left join cte on
    px.refkey = cte.addrid and
    cte.rn = 1

En supposant que cela ne le fasse pas :

  1. Lorsque vous dites qu'un XPIRDT nul a la priorité, voulez-vous dire même sur les dates d'entrée en vigueur les plus récentes, ou s'agit-il uniquement d'un bris d'égalité pour l'EFFECTDT le plus récent ? Si ce dernier, alors ce que j'ai devrait fonctionner. Si c'est le premier, alors nous devons changer l'ordre par dans la fonction analytique
  2. Je devine totalement en ce qui concerne le partyxref et mbr_person les tables. Si cela ne suffit pas, publiez peut-être des exemples de données et la sortie souhaitée pour inclure ces deux tables, ou modifiez-les ?