Reputation: 389
I needed to fill gaps between dates so i got this sql query:
select * from (
SELECT null as ID, to_date('15/08/28', 'yy/mm/dd') + ROWNUM - 1 as DATE_OF_RATE, null as VALUE, null as CURRENCY_ID
FROM dual
CONNECT BY LEVEL <= to_date('15/09/05', 'yy/mm/dd') - to_date('15/08/28', 'yy/mm/dd') + 1
) empCur
left join CURRENCY_RATE cr on TRUNC(empCur.DATE_OF_RATE) = (cr.DATE_OF_RATE)
AND cr.currency_id = 4;
Instead of hard coded dates above i need to pass min and max date_of_rate from currency_rate table. So i tried this, but i got diffrent result:
select * from (
SELECT null as ID, (select min(date_of_rate) from currency_rate) + ROWNUM - 1 as DATE_OF_RATE, null as VALUE, null as CURRENCY_ID
FROM dual
CONNECT BY LEVEL <= (select max(date_of_rate) - min(date_of_rate) + 1 from currency_rate)
) empCur
left join CURRENCY_RATE cr on TRUNC(empCur.DATE_OF_RATE) = (cr.DATE_OF_RATE)
where cr.date_of_rate between to_date('15/08/28', 'yy/mm/dd') and to_date('15/09/05', 'yy/mm/dd')
AND cr.currency_id = 4;
As you can see this didn't fill the gaps between date ranges. Is it even possible what i'm trying to achieve?
Upvotes: 0
Views: 1442
Reputation: 1269513
Your query is basically fine. The problem is the where
clause. That condition should be on the first table:
select *
from (select null as ID, (select min(date_of_rate) from currency_rate) + ROWNUM - 1 as DATE_OF_RATE, null as VALUE, null as CURRENCY_ID
from dual
connect by level <= (select max(date_of_rate) - min(date_of_rate) + 1 from currency_rate)
) empCur left join
CURRENCY_RATE cr
on empCur.DATE_OF_RATE = cr.DATE_OF_RATE and
cr.currency_id = 4
where empCur.DATE_OF_RATE >= date '2015-08-28' and
empCur.DATE_OF_RATE <= date '2015-09-05' ;
I don't see why TRUNC()
is necessary. If it is, just add it back in.
Upvotes: 1
Reputation: 98
I find using temp variables can help. Here's what I would do. Please note my syntax is probably shakey as I'm doing this from memory. Some light googling will get you the rest of the way though.
Step 1. Create some temp variables. These need to get run in one command.
DECLARE @MinDate DATETIME;
DECLARE @MaxDate DATETIME;
@MinDate = SELECT Min([DATE_OF_RATE]) FROM CURRENCY_RATE;
@MaxDate = SELECT Max([DATE_OF_RATE]) FROM CURRENCY_RATE;
Step 2. Create a calendar table of all possible dates, with literally date as the only column. Do this manually if you need to. You can always create a calendar table with days up to 2050, well after this system will no longer be in use.
Step 3. Do the left join from the calendar table to the rates table on the date. This will give you a row regardless of gaps in the rates.
SELECT c.CalDate FROM Calendar c
LEFT JOIN CURRENCY_RATE cr
ON c.CalDate = cr.DATE_OF_RATE
Step 4. Filter the new table where the date is in the min/max range using temp table
SELECT c.CalDate FROM Calendar c
LEFT JOIN CURRENCY_RATE cr
ON c.CalDate = cr.DATE_OF_RATE
WHERE c.CalDate >= @MinDate AND c.CalDate <= @MaxDate
I hope this helps.
Upvotes: 0