简体   繁体   中英

Finding dates between two dates (Best practice)

I have 2 SQL scripts. One like this:

"Date" > '2014-04-11' AND "Date" <= '2014-04-12'

the other one like this:

"Date" BETWEEN '2014-04-11' AND '2014-04-12'

Now i wonder if there is any specific best practice, one reason to do one over the other and if one of them is better for some apparent reason I missed somewhere down the road.

You are asking for best practices. I think the following is the best practice:

"Date" >= DATE '2014-04-11' AND "Date" < DATE '2014-04-12' + 1

First, note the use of the DATE keyword. You question is about dates and yet you are using a date format that Oracle does not directly support. Happily, Oracle support the ANSI standard DATE keyword with the ISO standard format.

Second, I added a +1 so you can see the end of the time period, which is presumably what you want to see in the code. It shouldn't affect performance because the + 1 is on a constant.

Third, a date constant has a time component. When none is specified, it is midnight on the date. So, the expression:

"Date" BETWEEN '2014-04-11' AND '2014-04-12'

Is really:

"Date" >= TIMESTAMP '2014-04-11 00:00:00' AND "Date" <= TIMESTAMP '2014-04-12 00:00:00'

That is, exactly one time from the later date is included, the first instant at midnight. This is not usually what you want. Oracle makes this problem worse in two ways:

  1. The date data type includes a time component.
  2. The default way of presenting date values has no time component.

So, to be safest, use the following rules:

  • Do not use between on dates.
  • Use >= for the first date.
  • User < for the second.

Aaron Bertrand has a blog on exactly this topic. Although it is specifically about SQL Server, many of the ideas apply to Oracle -- especially because the date data type in Oracle includes times.

SQL> create table date_tab as select sysdate + level d from dual connect by rownum < 10;

Table created.

Using between:

SQL> set autotrace traceonly
SQL> select * from date_tab where d between sysdate + 1 and sysdate + 3;


Execution Plan
----------------------------------------------------------
Plan hash value: 290508398

...

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(SYSDATE@!+1<=SYSDATE@!+3)
   2 - filter("D">=SYSDATE@!+1 AND "D"<=SYSDATE@!+3)

Using date intervals:

SQL> select * from date_tab where d > sysdate + 1 and d <= sysdate + 3;


Execution Plan
----------------------------------------------------------
Plan hash value: 290508398

...

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(SYSDATE@!+1<SYSDATE@!+3)
   2 - filter("D">SYSDATE@!+1 AND "D"<=SYSDATE@!+3)

As you can see, oracle optimizer rewrites the between predicate to "D">=SYSDATE@!+1 AND "D"<=SYSDATE@!+3 So if you use the second variant oracle performs less action than the first variant for one step.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM