Oracle SQL Select date range when dates are in varchar2 - sql

How should look Select date range when dates are in varchar2 dd/mm/yyyy?
When I use:
SELECT * FROM invoice
WHERE data_doc >= '01/07/2020'
AND data_doc <= '19/07/2020'
Returns values where data_doc is i.e. = 02/03/2020

When you compare strings (varchar2's in this case), you compare them lexicographically. One approach would be to convert those strings to actual dates:
SELECT *
FROM invoice
WHERE TO_DATE(data_doc, 'DD/MM/YYYY') >= TO_DATE('01/07/2020', 'DD/MM/YYYY') AND
TO_DATE(data_doc, 'DD/MM/YYYY') <= TO_DATE('19/07/2020', 'DD/MM/YYYY')

Use TO_DATE conversions everywhere
SELECT * FROM invoice
WHERE TO_DATE(data_doc,'DD/MM/YYYY') >= TO_DATE('01/07/2020','DD/MM/YYYY')
AND TO_DATE(data_doc,'DD/MM/YYYY') <= TO_DATE('19/07/2020','DD/MM/YYYY')

You (alas) need to convert the column to dates. The comparison can then be done directly to dates:
WHERE TO_DATE(data_doc, 'DD/MM/YYYY') >= DATE '2020-07-01' AND
TO_DATE(date_doc, 'DD/MM/YYYY') <= DATE '2020-07-17'
For performance, Oracle supports indexes on expressions. So, you can create an index on TO_DATE(data_doc, 'DD/MM/YYYY').
That said, you should fix your data model so dates are stored correctly as dates.
Because you are comparing dates in the same month -- and only for that reason -- you can adjust your comparison by requiring that the data be in the same month:
WHERE data_doc >= '01/07/2020' AND
data_doc <= '19/07/2020' AND
data_doc LIKE '__/07/2020'
I strongly recommend that you fix the data type, though.

Related

Filter by date in oracle SQL

I have a table with a date column (DD/MM/YYYY hh:mm:ss) as follows:
02/09/2021 09:50:37
03/09/2021 09:20:27
02/09/2021 14:05:25
03/09/2021 12:50:28
02/09/2021 14:25:26
What's the most efficient way to filter by date?
Note: I tried with
select date
from table
where date = '02/09/2021'
However, this provides results that wrongly lack the time and only contain the date 02/09/2021.
For example, 02/09/2021 09:50:37 would not be returned.
A simple option is
select *
from your_table
where trunc(date_column) = date '2021-09-02'
If there's an index on date_column, it wouldn't be used in that case so performance might suffer so you'll have to either create a function-based index, or use a different where clause:
where date_column >= date '2021-09-02' and date_column < date '2021-03-03'
If you want to return every record that has some date column equal to some date regardless to the time part then you need this:
select date
from table
where trunc(date) = '02/09/2021'
please avoid naming columns date and tables table.
Here is a small demo
Use a date range:
SELECT date_column
FROM table_name
WHERE date_column >= DATE '2021-09-02'
AND date_column < DATE '2021-09-02' + INTERVAL '1' DAY;
This will enable Oracle to use an index on the date_column column.
If you filter using:
TRUNC(date_column) = DATE '2021-09-02' or
TO_CHAR(date_column, 'DD-MM-YYYY') = '02-09-2021'
Then Oracle will not use an index on the date_column and would need a separate function-based index on either TRUNC(date_column) or TO_CHAR(date_column, 'DD-MM-YYYY').

DB2 date comparison

I'm trying to query a DB2 database to find records between two date columns, START_DATE and END_DATE (dates are stored in YYYYMMDD format in DB). This is what I have but it's not working. Could anyone please help me fix this?
SELECT *
FROM TBDeals
WHERE TIMESTAMP_FORMAT(START_DATE, 'YYYYMMDD') >= '2020-03-01'
AND TIMESTAMP_FORMAT(END_DATE, 'YYYYMMDD') <= '2020-04-20';
Thank you
You are storing dates as strings, which is not a good practice. On the other hand, the format that you are using does allow proper sorting, so why not simply check the existing values against strings, like so?
where startdate >= '20200301' and end_date <= '20200420'
The upside of this approach is that it can take advantage of indexes on the string dates columns.
If the values are numbers, then:
where startdate >= 20200301 and end_date <= 20200420
It seems that your date range is backwards, try this version:
SELECT *
FROM TBDeals
WHERE
TIMESTAMP_FORMAT(START_DATE, 'YYYYMMDD') >= '2020-03-20' AND
TIMESTAMP_FORMAT(END_DATE, 'YYYYMMDD') <= '2020-04-01';

Result empty when date variable

I'm using an Oracle 10g Database. I have a table with a lot of information. One of the columns has a type of DATE declared as follows DATE_INSERT DATE. I'm trying to make a query and have it filtered by a specific Date. When I use the function TO_CHAR() in the where clause I get the information as expected
SELECT * FROM TABLE WHERE TO_CHAR(DATE_INSERT, 'DD/MM/YYYY') = '05/10/2018'
But when I use a DATE variable or the TO_DATE() function I get an empty result set.
SELECT * FROM TABLE WHERE DATE_INSERT = TO_DATE('05/10/2018','DD/MM/YYYY')
OR
SELECT * FROM TABLE WHERE DATE_INSERT = date '2018-10-05';
OR (date_var defined as a date previously)
SELECT * FROM TABLE WHERE DATE_INSERT = date_var;
By a DB department requirement I need to get rid of all functions TO_DATE() / TO_CHAR(). Can you help me know why is the filtering not working when DATE types are used in the query?
This is due to the time component. I would recommend either:
WHERE DATE_INSERT >= date '2018-10-05' AND
DATE_INSERT < date '2018-10-06'
Or:
WHERE TRUNC(DATE_INSERT) = date '2018-10-05'
Oracle supports function-based indexes. If you want an index to be used, you can create an index to support either of these queries.
In Oracle, a DATE column always stores the date and the time information. So the query you mention:
SELECT * FROM TABLE WHERE TO_CHAR(DATE_INSERT, 'DD/MM/YYYY') = '05/10/2018'
doesn't use equality, but queries for a range. Which range? The whole day, that is 24 hours.
For the other query to you'll need to use a range, as in:
SELECT * FROM TABLE
WHERE DATE_INSERT >= TO_DATE('05/10/2018','DD/MM/YYYY')
AND DATE_INSERT < TO_DATE('06/10/2018','DD/MM/YYYY')
More clearly, to show the date & time info:
SELECT * FROM TABLE
WHERE DATE_INSERT >= TO_DATE('05/10/2018 00:00:00','DD/MM/YYYY HH24:MI:SS')
AND DATE_INSERT < TO_DATE('06/10/2018 00:00:00','DD/MM/YYYY HH24:MI:SS')

To_char for Oracle SQL not working

i have the following query which does not retrieve data even though there is:
select *
from INTERFACE_RUN
where TO_CHAR(INTERFACE_RUN.START_TIME, 'dd-mon-yy') = '04-MAY-10';
The start_time field is a timestamp field. Hence I converted it using to_char and compared with the user passed value of 04-MAY-10. But it did not fetch any data.
Any help please. Thanks in advance
to_char() pays attention to the case of the pattern. So, you are producing `04-may-10', which is not the same.
So, try this:
where TO_CHAR(INTERFACE_RUN.START_TIME, 'DD-MON-YY') = '04-MAY-10';
That said, I much prefer:
where trunc(INTERFACE_RUN.START_TIME) = date '2010-05-04'
or:
where INTERFACE_RUN.START_TIME >= date '2010-05-04' AND
INTERFACE_RUN.START_TIME < (date '2010-05-04') + 1
Why? For two reasons. First, the column is a date, so I prefer date comparisons. Second, I prefer the ANSI/ISO standard date formats. The second version can also readily take advantage of an index on the START_TIME column.
Oracle will convert the date to lowercase, thus generating '04-may-10'
Try with 'DD-MON-YY' (uppercase)
select TO_CHAR(sysdate, 'dd-mon-yy') from dual
union all
select TO_CHAR(sysdate, 'dd-MON-yy') from dual;
TO_CHAR(S
---------
13-jun-16
13-JUN-16

YYYYMMDD to YYYYMM in oracle

I have a column with DATE datatype in a table.
I am trying to retrieve the column values in YYYYMM format. My select query looks like below
select *
from tablename
where date column = to_char(to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM');
I am getting below exception.
ORA-01847: day of month must be between 1 and last day of month
Appreciate any input on this.
I think the simplest method is:
where to_char(datecolumn, 'YYYYMM') = '400012'
Or, if you prefer:
where to_char(datecolumn, 'YYYYMM') = to_char(to_date('12/31/4000', 'MM/DD/YYYY'), 'YYYYMM');
Syntax-wise, the right hand date (to the right of the equals) is OK. But you are doing a character comparison, not a date comparison.
This works for me in multiple databases:
select to_char (to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM')
from dual;
Even though your column is named DATE_COLUMN, you are comparing based on characters in the query.
So, try this instead - this compares based on dates (NOT a character comparison) and truncates off the hour, minute, ETC. so you are only comparing the DAY:
select * from DATE_TAB
where TRUNC(DATE1, 'DDD') = TRUNC(to_date('12/31/4000','MM/DD/YYYY'),'DDD');
NOTE: The DATE1 field above is a DATE field. If you're DATE_COLUMN is not a DATE field, you must
convert it to a DATE datatype first (using TO_DATE, ETC.)
Assuming that "date_column" is actually a date, and that you have an index on date_column, you can do something like this to return the data quickly (without truncating dates in all rows to do a comparison):
with dat as (
select level as id, sysdate - (level*10) as date_column
from dual
connect by level <= 100
)
select id, date_column
from dat
where date_column between to_date('11/1/2013', 'MM/DD/YYYY') and last_day(to_date('11/2013 23:59:59', 'MM/YYYY HH24:MI:SS'))
Here I just dummy up some data with dates going back a few years. This example picks all rows that have a date in the month of November 2013.
If your date_column's data-type is DATE, then use
select *
from tablename
where TO_CHAR(date_column,'YYYYMM') = to_char (to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM');
If your date_column's data-type is VARCHAR, then use:
select *
from tablename
where date_column = to_char (to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM');
I somehow feel your error is because you have a space between date and column as
"date column". If the field name in the table is "COLUMN", then just removing the word "DATE" from your original query would suffice, as:
select *
from tablename
where column = to_char(to_date('12/31/4000','MM/DD/YYYY'),'YYYYMM');
If your column (YYYYMMDD) is in number format, the simplest way to get YYYYMM would be
select floor(DATE/100)
from tablename;