Oracle date "Between" Query Oracle date "Between" Query sql sql

Oracle date "Between" Query


Judging from your output it looks like you have defined START_DATE as a timestamp. If it were a regular date Oracle would be able to handle the implicit conversion. But as it isn't you need to explicitly cast those strings to be dates.

SQL> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss'  2  /Session altered.SQL>SQL> select * from t23  2  where start_date between '15-JAN-10' and '17-JAN-10'  3  /no rows selectedSQL> select * from t23  2  where start_date between to_date('15-JAN-10') and to_date('17-JAN-10')  3  /WIDGET                          START_DATE------------------------------  ----------------------Small Widget                    15-JAN-10 04.25.32.000    SQL> 

But we still only get one row. This is because START_DATE has a time element. If we don't specify the time component Oracle defaults it to midnight. That is fine for the from side of the BETWEEN but not for the until side:

SQL> select * from t23  2  where start_date between to_date('15-JAN-10')   3                       and to_date('17-JAN-10 23:59:59')  4  /WIDGET                          START_DATE------------------------------  ----------------------Small Widget                    15-JAN-10 04.25.32.000Product 1                       17-JAN-10 04.31.32.000SQL>

edit

If you cannot pass in the time component there are a couple of choices. One is to change the WHERE clause to remove the time element from the criteria:

where trunc(start_date) between to_date('15-JAN-10')                             and to_date('17-JAN-10')

This might have an impact on performance, because it disqualifies any b-tree index on START_DATE. You would need to build a function-based index instead.

Alternatively you could add the time element to the date in your code:

where start_date between to_date('15-JAN-10')                      and to_date('17-JAN-10') + (86399/86400) 

Because of these problems many people prefer to avoid the use of between by checking for date boundaries like this:

where start_date >= to_date('15-JAN-10') and start_date < to_date('18-JAN-10')


You need to convert those to actual dates instead of strings, try this:

SELECT *FROM <TABLENAME>WHERE start_date BETWEEN TO_DATE('2010-01-15','YYYY-MM-DD') AND TO_DATE('2010-01-17', 'YYYY-MM-DD');

Edited to deal with format as specified:

SELECT *FROM <TABLENAME>WHERE start_date BETWEEN TO_DATE('15-JAN-10','DD-MON-YY') AND TO_DATE('17-JAN-10','DD-MON-YY');


As APC rightly pointed out, your start_date column appears to be a TIMESTAMP but it could be a TIMESTAMP WITH LOCAL TIMEZONE or TIMESTAMP WITH TIMEZONE datatype too. These could well influence any queries you were doing on the data if your database server was in a different timezone to yourself. However, let's keep this simple and assume you are in the same timezone as your server. First, to give you the confidence, check that the start_date is a TIMESTAMP data type.

Use the SQLPlus DESCRIBE command (or the equivalent in your IDE) to verify this column is a TIMESTAMP data type.

eg

DESCRIBE mytable

Should report :

Name        Null? Type----------- ----- ------------NAME              VARHAR2(20) START_DATE        TIMESTAMP

If it is reported as a Type = TIMESTAMP then you can query your date ranges with simplest TO_TIMESTAMP date conversion, one which requires no argument (or picture).

We use TO_TIMESTAMP to ensure that any index on the START_DATE column is considered by the optimizer. APC's answer also noted that a function based index could have been created on this column and that would influence the SQL predicate but we cannot comment on that in this query. If you want to know how to find out what indexes have been applied to table, post another question and we can answer that separately.

So, assuming there is an index on start_date, which is a TIMESTAMP datatype and you want the optimizer to consider it, your SQL would be :

select * from mytable where start_date between to_timestamp('15-JAN-10') AND to_timestamp('17-JAN-10')+.9999999

+.999999999 is very close to but isn't quite 1 so the conversion of 17-JAN-10 will be as close to midnight on that day as possible, therefore you query returns both rows.

The database will see the BETWEEN as from 15-JAN-10 00:00:00:0000000 to 17-JAN-10 23:59:59:99999 and will therefore include all dates from 15th,16th and 17th Jan 2010 whatever the time component of the timestamp.

Hope that helps.

Dazzer