Ainda não entendi qual disco, no seu exemplo, você queria, então deixe-me dar algumas alternativas.
Eu deduzi de sua declaração de problema que você deseja a data efetiva mais recente das disponíveis. Como há laços envolvidos, você não pode usar
max()
(como você já declarou) e row_number()
é o caminho a seguir: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
A próxima parte foi onde você me perdeu com os nulos... Se sua classificação secundária for por data de expiração e você quiser que um valor nulo supere a última data de expiração, então você faria o pedido pela data de expiração e colocaria
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
O que significa que esta linha é a vencedora:
10948448 5/14/2015 <null>
Se, no entanto, você quiser que os nulos sejam considerados apenas se não houver datas de expiração, você pode usar
nulls last
(ou omita, pois é o padrão):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
Significando que esse cara ganhou o prêmio:
10948448 5/14/2015 5/13/2015
Como isso usa
row_number()
você não perderá nenhuma linha - cada linha terá um número de linha. É só que, se houver empates verdadeiros, é um sorteio sobre qual linha é escolhida. No entanto, seu problema com datas de expiração nulas não deve causar problemas com essa abordagem. -- editado 13/02/16 --
Acho que estou começando para entender seu problema, mas não tenho 100% de certeza. Eu incorporei trechos do seu código com a junção à esquerda com minha sugestão e a necessidade de ter datas de expiração nulas primeiro, e este é meu próximo 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
Supondo que isso não faça isso:
- Quando você diz que um XPIRDT nulo tem precedência, você quer dizer até mesmo em datas efetivas mais recentes ou é apenas um critério de desempate para o EFFECTDT mais recente? Se o último, então o que eu tenho deve funcionar. Se for o primeiro, precisamos mudar a ordem por na função analítica
- Estou totalmente adivinhando quando se trata da
partyxref
embr_person
mesas. Se isso não resolver, talvez poste alguns dados de exemplo e a saída desejada para incluir essas duas tabelas ou mexa-se?