Reputation: 1
I am seeing different results for a query whenever I rearrange the conditions of the where clause; I am trying to figure out why this is. I was given to try and figure out what is going on, so I could use some help to ascertain what may be causing an issue. To be clear, we are not receiving errors when running the select statement, but receiving unintended data results. This is an Oracle database (10-g I believe). We have two conditions for the same field. The first is to make sure the results are greater than 30 years ago (this database was not set my by myself, but the team that owns the application decided to change the created_date to 30 in the past was a good idea).....the second is to have a more specific date range of September 1st to October 1st.
SELECT created_date
FROM tableName
WHERE
created_date > sysdate - 11000 -- 30 years in the past
AND short_name like 'FOO%'
AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
AND TO_DATE('10-01-2017', 'MM-DD-YYYY')
When running the query above, we receive results with a created_date outside of the condition at the end of the where clause.
However, when I place the comparison between the created_date and the sysdate AFTER the comparison between the two dates, we receive the correct results.
SELECT created_date
FROM tableName
WHERE
short_name like 'FOO%'
AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
AND TO_DATE('10-01-2017', 'MM-DD-YYYY')
AND created_date > sysdate - 11000 -- 30 years in the past
Also, I removed the trunc portion of "AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY') " to "AND created_date BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY') " and received the intended results with the sysdate comparison before or afterward.
SELECT created_date
FROM tableName
WHERE
created_date > sysdate - 11000 -- 30 years in the past
AND short_name like 'FOO%'
AND created_date BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
AND TO_DATE('10-01-2017', 'MM-DD-YYYY')
EDIT:
There are numerous records in the database. There is only 1 result with a created_date of 22-Sep-17.
SELECT created_date
FROM tableName
WHERE
created_date > sysdate - 11000 -- 30 years in the past
AND short_name like 'FOO%'
AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
AND TO_DATE('10-01-2017', 'MM-DD-YYYY')
Produces 25 entries with a created_date of 17-Feb-04 and 1 with 22-Sep-17.
These will give two subtly different results for the values between 2017-10-01 00:00:01 and 2017-10-01 23:59:59. The query using TRUNC will include that range where without TRUNC that range will be excluded.
The intended result is to have on record returned back within the date range 22-Sep-17; however, we are receiving 25 records all with dates of 17-Feb-04....If I remove the created_date > sysdate - 11000 I receive the only one record as well.
Upvotes: 0
Views: 5463
Reputation: 167962
The first is to make sure the results are greater than 30 years ago
You aren't subtracting 30 years, you are subtracting 11,000 days which is approximately (depending on leap years) 30 years and 42 days.
If you want to subtract 30 years then use:
ADD_MONTHS( date_value, -30 * 12 )
the second is to have a more specific date range of September 1st to October 1st.
This makes the first condition irrelevant - if it is between 2017-09-01
and 2017-10-01
then it will be within the last 30 years and you do not need that first condition.
I removed the trunc portion of "
AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
" to "AND created_date BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
" and received the intended results with the sysdate comparison before or afterward.
These will give two subtly different results for the values between 2017-10-01 00:00:01
and 2017-10-01 23:59:59
. The query using TRUNC
will include that range where without TRUNC
that range will be excluded.
Also, using TRUNC
means that Oracle will not us an index on the created_date
column (and would require a function-based index on TRUNC( created_date )
). If you want to use an index then just use the column and test to see if it is greater or equal than the start of the range and less than the end of the range plus one day (to include up to 23:59:59 of that day).
The simplified equivalent of your TRUNC
query is:
SELECT created_date
FROM tableName
WHERE short_name like 'FOO%'
AND created_date >= DATE '2017-09-01' -- range start
AND created_date < DATE '2017-10-01' + INTERVAL '1' DAY -- range end + 1 day
Upvotes: 1