Reputation: 107
I apologize if the title is ambiguous, but I couldn't think of a better way to distill down my objective.
I have two tables: AcctProdHist ph
and AcctBalHist bh
that I have aliased ph and bh, respectively. AcctProdHist
has the product history for an account and its productdate
. AcctBalHist
contains a history of the account balance by date balance changed balancedate
.
I am trying to find the balance
in AcctBalHist
for the balancedate
nearest the productdate
in AcctProdHist
. There are two situations:
Here is my code for combining both tables and getting a full balance history:
select
ph.acctnbr,
ph.product,
ph.productdate,
bh.balancedate,
bh.balance
from AcctProdHist ph, AcctBalHist bh
where ((ph.acctnbr = bh.acctnbr(+)))
and ph.acctnbr in (12345,67890)
Here are the results:
ACCTNBR Product ProductDate BalanceDate Balance
12345 BYBU 7/16/2018 8/1/2018 550
12345 BYBU 7/16/2018 7/31/2018 510
12345 BYBU 7/16/2018 7/12/2018 500
12345 BYBU 7/16/2018 7/11/2018 460
12345 BYBU 7/16/2018 7/2/2018 450
67890 ABAU 7/20/2018 8/5/2018 103
67890 ABAU 7/20/2018 8/1/2018 102
67890 ABAU 7/20/2018 7/31/2018 101
67890 ABAU 7/20/2018 7/22/2018 100
In this case, the Balance
I want for ACCTNBR
12345 is 500. The Balance
I want for ACCTNBR
67890 is 100.
I'm guessing i'll have to do a UNION query as i'm working with two different situations, but I don't even know where to start.
Thanks!
EDIT: Adding Sample Data from the individual tables.
AcctProdHist
ACCTNBR Product ProductDate InactiveDate
12345 ATRU 5/1/2016 7/16/2018
12345 BYBU 7/16/2018
67890 ABAU 7/20/2018
AcctBalHist
ACCTNBR BalanceDate Balance
12345 1/1/2018 225
12345 2/6/2018 268
12345 4/20/2018 315
12345 6/1/2018 400
12345 7/2/2018 450
12345 7/11/2018 460
12345 7/12/2018 500
12345 7/31/2018 510
12345 8/1/2018 550
67890 7/22/2018 100
67890 7/31/2018 101
67890 8/1/2018 102
Upvotes: 1
Views: 187
Reputation: 94859
You must rank your rows. Use ROW_NUMBER
for this, giving the closest balance record #1:
select
acctnbr,
product,
productdate,
balancedate,
balance,
from
(
select
ph.acctnbr,
ph.product,
ph.productdate,
bh.balancedate,
bh.balance,
row_number() over (partition by ph.acctnbr
order by case when ph.productdate >= bh.balancedate then 1 else 2 end,
abs(ph.productdate - bh.balancedate)
) as rn
from AcctProdHist ph
left join AcctBalHist bh on bh.acctnbr = ph.acctnbr
where ph.acctnbr in (12345,67890)
)
where rn = 1
order by acctnbr;
Upvotes: 1