Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle-Join-Bedingung mit Top 1

Mir ist immer noch nicht klar, welche Platte Sie in Ihrem Beispiel wollten, also lassen Sie mich Ihnen einige Alternativen nennen.

Ich habe aus Ihrer Problembeschreibung entnommen, dass Sie das späteste Wirksamkeitsdatum der verfügbaren haben möchten. Da es um Bindungen geht, können Sie max() nicht verwenden (wie Sie bereits gesagt haben) und row_number() ist der richtige Weg:

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

Der nächste Teil war, wo Sie mich mit den Nullen verloren haben ... Wenn Ihre sekundäre Sortierung nach Ablaufdatum ist und Sie möchten, dass ein Nullwert das späteste Ablaufdatum übertrumpft, dann würden Sie nach dem Ablaufdatum bestellen und 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

Das bedeutet, dass diese Zeile der Gewinner ist:

10948448    5/14/2015   <null>

Wenn Sie jedoch möchten, dass Nullen nur berücksichtigt werden, wenn es keine Ablaufdaten gibt, können Sie nulls last verwenden (oder weglassen, da es die Voreinstellung ist):

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

Das heißt, dieser Typ hat den Preis gewonnen:

10948448    5/14/2015   5/13/2015

Da dies row_number() verwendet Sie werden keine Zeilen verlieren – jede Zeile hat garantiert eine Zeilennummer. Es ist nur so, dass, wenn es echte Gleichstände gibt, es ein Toss-Up ist, welche Reihe gewählt wird. Ihr Problem mit null Ablaufdaten sollte jedoch bei diesem Ansatz keine Probleme verursachen.

-- bearbeiten 13.02.16 --

Ich glaube, ich beginne um dein Problem zu verstehen, bin mir aber nicht 100% sicher. Ich habe Ausschnitte Ihres Codes mit der linken Verknüpfung mit meinem Vorschlag und der Notwendigkeit, zuerst Null-Ablaufdaten zu haben, integriert, und dies ist mein nächster 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

Angenommen, dies tut es nicht:

  1. Wenn Sie sagen, dass ein Null-XPIRDT Vorrang hat – meinen Sie das sogar über jüngere Wirksamkeitsdaten, oder ist es nur ein Tiebreaker für den neuesten EFFECTDT? Wenn letzteres, dann sollte das, was ich habe, funktionieren. Wenn ersteres der Fall ist, müssen wir die Reihenfolge in der Analysefunktion ändern
  2. Bei partyxref vermute ich total und mbr_person Tische. Wenn dies nicht ausreicht, posten Sie vielleicht einige Beispieldaten und die gewünschte Ausgabe, um diese beiden Tabellen einzubeziehen, oder fummeln Sie daran herum?