8

How do I select dates between two given dates in an Oracle query?

1

7 Answers 7

17
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

Sign up to request clarification or add additional context in comments.

6 Comments

-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, 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
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.
Anything 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.
suppose if i need to take startdate as sysdate(current date) instead of specific date what can i do?
|
6
SELECT * FROM your_table WHERE your_date_field BETWEEN DATE '2010-01-01' AND DATE '2011-01-01';

5 Comments

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
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.
@Ronnis - rather than just down voting how about you answer the question and supply an alternative?
@Andy Paton, I'd rather upvote yours if you used to_Date or DATE literals.
ok you two, stop fighting or I'll take your toys away... and downvote you both.
5

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.

Comments

1

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);

Comments

0

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;

Comments

-1

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.

Comments

-1

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');

1 Comment

this query doesn't generate a list of dates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.