Normally when we need to compare DATE type where only DATE (i.e DD/MM/YYYY) component holds the significant, we need to convert DATE into VARCHAR2 or use TRUNCATE as follows so that only date component is compare(not time):
Assume I have index on balance_date.
SELECT balance_amount
FROM balances
WHERE
TO_CHAR(balance_date,’YYYYMMDD’)
= TO_CHAR(sysdate,’YYYYMMDD’);
After running the explain plan for above statement it shows me:
PLAN_TABLE_OUTPUT
—————————————
Plan hash value: 4006579748—————————————
| Id | Operation | Name |
—————————————
| 0 | SELECT STATEMENT | |
|* 1 | TABLE ACCESS FULL| BALANCES |
—————————————
OR
SELECT balance_amount
FROM balances
WHERE TRUNC(balance_date) = TRUNC(sysdate);
After running the explain plan for above statement it shows me:
PLAN_TABLE_OUTPUT
—————————————
Plan hash value: 4006579748—————————————
| Id | Operation | Name |
—————————————
| 0 | SELECT STATEMENT | |
|* 1 | TABLE ACCESS FULL| BALANCES |
—————————————
We notice that even though we have index on balance_date, its use is suppress due to use of function on balance_date.
We can perform same comparison with better efficiency by rewriting above queries as follows:
SELECT balance_amount
FROM balances
WHERE
balance_date BETWEEN
TRUNC(sysdate)
AND
TO_DATE( TO_CHAR(sysdate,’YYYYMMDD’)||’23:59:59′,’YYYYMMDDHH24:MI:SS’);
or based on zfriese comments:
SELECT balance_amount
FROM balances
WHERE
balance_date >= TRUNC(sysdate)
AND balance_date < TRUNC(sysdate) + 1
PLAN_TABLE_OUTPUT
—————————————————-
Plan hash value: 3073005708—————————————————-
| Id | Operation | Name
—————————————————-
| 0 | SELECT STATEMENT |
|* 1 | FILTER |
| 2 | TABLE ACCESS BY INDEX ROWID| BALANCES
|* 3 | INDEX RANGE SCAN | BALANCES_IDX
—————————————————-
3 responses so far ↓
1 zfriese // Aug 17, 2007 at 10:07 pm
SELECT balance_amount
FROM balances
WHERE
balance_date BETWEEN
TRUNC(sysdate)
AND
TO_DATE( TO_CHAR(sysdate,’YYYYMMDD’)||’23:59:59′,’YYYYMMDDHH24:MI:SS’);
Looks like the long way around the barn. How about…
SELECT balance_amount
FROM balances
WHERE
balance_date >= TRUNC(sysdate)
AND balance_date < TRUNC(sysdate) + 1
Same execution plan.
2 Rajender Singh // Aug 18, 2007 at 10:13 am
That’s a cherry on the pie!
Thanks!
3 Roopal // Sep 26, 2008 at 10:20 am
I need a select statement where the data returned is for the first day of every month i.e.
SELECT Balance_amount
FROM Balances
and then the condition is that balance amount retrieved is for the first day of every month - the format of the date field is dd/mm/yyy - so data is retrieved only where dd = 1
Leave a Comment