How do I select dates between two given dates in an Oracle query?
-
See also [Generate a range of dates using SQL](https://stackoverflow.com/questions/418318/generate-a-range-of-dates-using-sql) – Vadzim May 13 '20 at 16:21
7 Answers
SELECT TO_DATE('12/01/2003', 'MM/DD/YYYY') - 1 + rownum AS d
FROM all_objects
WHERE TO_DATE('12/01/2003', 'MM/DD/YYYY') - 1 + rownum <= TO_DATE('12/05/2003', 'MM/DD/YYYY')
from
http://forums.devshed.com/oracle-development-96/select-all-dates-between-two-dates-92997.html

- 9,736
- 13
- 49
- 60
-
-1 This code example (from the linked page) is answering a slightly different question, and is more complicated than needed for the question asked here. – payne Feb 18 '11 at 12:28
-
@payne, Greg has given the best answer so far. All others *assume* that there is a table involved. Granted, that's possibly what the OP *wanted* (as opposed to *did*) ask, but then again, if someone is too lazy to state exactly what he wants, he should get what he asked for. Therefore +1 – René Nyffenegger Feb 18 '11 at 12:32
-
I guess with the slightly vague requirement it wasn't clear that the OP wanted to select from a table - I guess we'll find out if and when an answer is accepted. – Greg Reynolds Feb 18 '11 at 14:34
-
2Anything based on a table is predicated on the notion that your date range will be less than the number of rows in the table. If you happen to pass in a big date range this solution fails. Which is why using the LEVEL pseudocolumn like my solution is preferable as it is valid for any arbitrarty range. – Michael Broughton Feb 18 '11 at 14:46
-
suppose if i need to take startdate as sysdate(current date) instead of specific date what can i do? – Prabakaran Feb 19 '11 at 04:47
-
Just replace the to_date('12/01/2003', 'MM/DD/YYYY') entries with current_timestamp – Greg Reynolds Feb 22 '11 at 10:58
SELECT * FROM your_table WHERE your_date_field BETWEEN DATE '2010-01-01' AND DATE '2011-01-01';

- 17,340
- 3
- 31
- 31
-
Who said anything about Jan 1st 2010 to Jan 1st 2011, I just aswell might ask. What is the difference??? sysdate is a date just as Jan 1st 2010 – Klaus Byskov Pedersen Feb 18 '11 at 12:30
-
well because sysdate is slightly different to a usual date, and without explaination of what sysdate does - it would make more sense to stick with a traditional date. Nothing wrong with SysDate - but it needs a bit more explanation that you provided. – diagonalbatman Feb 18 '11 at 12:32
-
@Ronnis - rather than just down voting how about you answer the question and supply an alternative? – diagonalbatman Feb 18 '11 at 16:02
-
@Andy Paton, I'd rather upvote yours if you used to_Date or DATE literals. – Ronnis Feb 18 '11 at 16:09
-
1ok you two, stop fighting or I'll take your toys away... and downvote you both. – Jeffrey Kemp Feb 19 '11 at 09:23
You can use the LEVEL pseudocolumn in a tricky way to generate a series, so, for example, to get the list of days between today and 20 days from now I can:
select trunc(sysdate+lvl) from
(select level lvl from dual connect by level < ((sysdate+20)-sysdate - 1) )
order by 1
Generically you can see how this would apply for any two given dates.
select trunc(early_date+lvl) from
(select level lvl from dual connect by level < (later_Date-early_date-1) )
order by 1
And you can adjust the clauses if you want to include the two end dates as well.

- 12,593
- 2
- 32
- 52

- 4,045
- 14
- 12
You could also use the below to get a list of calendar dates between a date range (similar to Michael Broughton's solution)
select (trunc(sysdate) - (trunc(sysdate) - (to_date('start_date')))) -1 + level from dual
connect by level <=
((select (trunc(sysdate) - (trunc(sysdate) - (to_date('end_date'))))-
(trunc(sysdate) - (trunc(sysdate) - (to_date('start_date'))))from dual)+1);

- 11
- 2
I do this so often for a scheduling app I work on that I created a pipelined table function. Sometimes I need days, hours or 15 minutes between times. This is not exactly my function, because my code is in a package. For example, here, I'm getting days between Jan 1 2020 and Jan 10 2020:
SELECT
days.date_time
FROM
table(between_times(TO_DATE('2020-01-01'),TO_DATE('2020-01-10'),(60*24), 'Y')) days
The pipelined function:
function between_times(i_start_time TIMESTAMP, i_end_time TIMESTAMP, i_interval_in_minutes NUMBER, include_end_time VARCHAR2 := 'N')
RETURN DateTableType PIPELINED
AS
time_counter TIMESTAMP := i_start_time;
BEGIN
IF i_start_time IS NULL OR i_end_time IS NULL or i_start_time > i_end_time OR i_interval_in_minutes IS NULL OR
i_interval_in_minutes <= 0 THEN
RETURN;
END IF;
LOOP
-- by default does not include end time
if (include_end_time = 'Y') THEN
exit when time_counter > i_end_time;
ELSE
exit when time_counter >= i_end_time;
END IF;
pipe row(DateType( time_counter ));
time_counter := time_counter + i_interval_in_minutes/(60*24);
END LOOP;
EXCEPTION WHEN NO_DATA_NEEDED THEN NULL;
END;

- 371
- 5
- 20
with all_days as (select trunc(to_date('12-03-2017','dd-mm-yyyy')+levl)-1 as all_dates from (select level levl from dual connect by level < (sysdate-to_date('12-03-2017','DD-MM-YYYY')+1) ) order by 1) select count(*) as no_of_days from all_days where ltrim(rtrim(to_char(all_dates,'DAY'))) not in ('SATURDAY','SUNDAY');
Use "between". In a general sense:
select * from someTable where dateCol between date1 and date2;
note that dateCol is defined as a date and date1 and date2 are also date values. If these aren't dates, then you'll convert them to dates using to_date function.

- 15,107
- 3
- 33
- 40