How to use datediff equivalent in Oracle with YYYYMMDD formatted number? - sql

I have Oracle database columns with the number format YYYYMMDD. I have not been successful in using this format with datediff to get the difference between two dates. The documentation I've read online uses a different format:
DATEDIFF(day,'2008-06-05','2008-08-05')
What's the best way for me to get number of days between two dates given the format available to me in Oracle? Answers not involving datediff are acceptable as long as it gets the number of days between two dates with the format YYYYMMDD.

Simple subtraction in Oracle:
SELECT TO_DATE('20080805','YYYYMMDD') - TO_DATE('20080605','YYYYMMDD')
FROM DUAL;

Oracle doesn't have a DATEDIFF() function. Instead, you can use simple arithmetic with Oracle dates, where subtracting one date from another gives the number of days, and where you can add an subtract days from a given date. (You can also subtract fractions of days, but that might be outside the scope of this answer.)
To convert your NUMBER dates of the format YYYYMMDD to actual dates, just use the TO_DATE() function (I am pretty sure that Oracle will implicitly convert the NUMBER value to a VARCHAR2 before converting to a date; if not, use TO_CHAR() to do that explicitly).
TO_DATE(20150301, 'YYYYMMDD')
To get the difference between two dates, you can do the following:
SELECT TO_DATE(my_number_date1, 'YYYYMMDD') - TO_DATE(my_number_date2, 'YYYYMMDD')
FROM my_table;
Incidentally, if you want to get intervals instead of days, convert to timestamp (using TO_TIMESTAMP()) instead of converting to date.

Related

SQLite strftime() returning null with integers

I have a date with the column name "date" in my table "productions" stored as integer with Unix format ( example: 1548263300000). And I want to retrieve only the year. When I do:
SELECT strftime('%Y ',date) as year
FROM productions
it returns null.
When I change the type to TEXT into my table and I store the date in string format ( example 2020-05-01 ), the same sql returns me "2020" which is correct and what I was looking for.
Why strftime() doesn't work with integers since the SQLite documentation say you can work with TEXT,INTEGER and REAL for dates? How to use date functions with integers?
extra information:
In this tutorial, they also use strftime with integers and it seems to work for them, so I understand from that, that the functions are available no matter what type you use ( text,int,real): link
when I use:
SELECT strftime('%Y',DATETIME(ROUND(date/ 1000), 'unixepoch'))
FROM productions;
it works fine, but I don't understand why I have to do all this when I use integers but when I use text, it works directly.
You can use strftime() but you have to add the 'unixepoch' modifier:
strftime('%Y', date / 1000, 'unixepoch')
so your date / 1000 is recognized as the number of seconds since 1970-01-01.
From Date And Time Functions:
The "unixepoch" modifier (11) only works if it immediately follows a
timestring in the DDDDDDDDDD format. This modifier causes the
DDDDDDDDDD to be interpreted not as a Julian day number as it normally
would be, but as Unix Time - the number of seconds since 1970.

Unable to get data between two years

I am not getting data between two years, below is between condition
to_char(Wfc.APPLYDTM,'MM/DD/YYYY') between '12/11/2019' and '01/10/2020'
but I am getting data between '12/11/2019' and '12/31/2019' & '01/11/2020' and '01/01/2020' for these dates but not between two different years.
Please help
Try using TO_DATE instead of TO_CHAR, and then compare against valid Oracle date literals:
SELECT *
FROM Wfc
WHERE TO_DATE(APPLYDTM, 'MM/DD/YYYY') BETWEEN date '2019-12-11' AND date '2019-01-10';
Note that if APPLYDTM already be a date, then you don't need to call TO_DATE on it. It doesn't make sense to convert your data to character, if you intend to work with it as a date.
You should convert your data to Date to be able to compare correctly.
The main idea is you should compare date value instead of string value.
to_date(Wfc.APPLYDTM,'MM/dd/yyyy') between to_date('12/11/2019','MM/dd/yyyy') and to_date('01/10/2020','MM/dd/yyyy')
Read here to more details.
Do not convert date/time values to strings! Use the built in functionality.
Your logic is most simply expressed as:
Wfc.APPLYDTMbetween >= DATE '2019-12-11' AND
Wfc.APPLYDTMbetween < DATE '2020-01-11'
Note that the date constants are provided using the DATE keyword. This supposed ISO 8601 standard date formats (happily!).
Also note the use of >= and < rather than BETWEEN. The date data type in Oracle can include a time component -- even if you don't see it when you query the table. This ensures that all date/times are included in the range.
As an added benefit, this can use an index on (APPLYDTMbetween). Using a function usually precludes using an index, unless you have defined a function-based index.

Comparing a date and getting result of records having further dates

I am using sql for database connectivity. I am filtering records in database on date basis using sql query which consists of function convert(varchar(100),column name,106). I am comparing it with date having dd/MMM/yyyy format. As a result I get records of next all the dates.
Example: If I try to filter the table by 01/June/2017 then inspite of having records of that date, I get records of next all the dates. I am not able to get records of 01/June/2017.
I have used greater than or equal to expression.
It is better to convert it to this yyyymmdd number format and do the comparison as below:
select convert(int,convert(varchar(10),[your column],112))
20170529
Don't convert your dates into any format (=strings) when doing comparison. Always use the date (or datetime etc) format. That way you will be comparing the actual values, not string or numeric comparison. Here the problem is that format 106 is dd mon yyyy so it will never match your date because it's a string dd/MMM/yyyy but you will get any dates starting with 02 anyhow, for example 02/Jan/1990, because in alphabetical order that will come after your given date.

SQL Date Format Conversion

I have a question regarding SQL dates.
The table I am working with has a date field in the following format: "22-SEP-08". The field is a date column.
I am trying to figure out how to output records from 1/1/2000 to present day.
The code below is not filtering the date field:
Select distinct entity.lt_date
from feed.entitytable entity
where entity.lt_date >= '2000-01-01'
Any help regarding this issue is much appreciated. Thanks!
Edit: I am using Oracle SQL Developer to write my code.
DATEs do not have "a format". Any format you see is applied by the application displaying the date value.
You can either change the configuration of SQL Developer to display dates in a different format, or you can use to_char() to format the date the way you want.
The reason your statement does not work, is most probably because of the implicit data type conversion that you are relying on.
'2000-01-01' is a string value, not a date. And the string is converted using the NLS settings of your session. Given the fact that you see dates displayed as DD-MON-YY means that that is the format that is used by the evil implicit data type conversion. You should supply date values always as real date literals.
There are two ways of specifying a real date literal. The first is ANSI SQL and simple uses the keyword DATE in front of an ISO formatted string:
where entity.lt_date >= DATE '2000-01-01'
Note the DATE keyword in front of the string, wich makes it a real date literal not a string expression.
The other option is to use to_date() to convert a character value into a date:
where entity.lt_date >= to_date('2000-01-01', 'yyyy-mm-dd');
More details about specifying date literals can be found in the manual:
Date literals
to_date function
My guess is the data type isn't a Date. Just in case its a char type, try to convert it using the Oracle TO_DATE() function. The Oracle documentation below should help you with parameters.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions183.htm
An implicit datatype conversion bites once again.
You're right. The predicate is not doing the comparison you are expecting,
Oracle is performing an implicit datatype conversion, from DATE to VARCHAR, so that it can do a comparison to the string literal.
If lt_date column is DATE datatype, then Oracle is seeing your where clause:
where entity.lt_date >= '2000-01-01'
Oracle is actually seeing it as if it's written like this:
where TO_CHAR(entity.lt_date) >= '2000-01-01'
And that's where the "format" problem comes in. The column itself does not have a "format". Because the second argument to the TO_CHAR function is not supplied, Oracle is using the value of the NLS_DATE_FORMAT parameter (from your session). And that's probably set to DD-MON-YY. Which is why that's the "format" you're seeing when you a run a SELECT statement in SQL*Plus. Because the DATE value is (again) being run through a TO_CHAR function to get a string that can be displayed.
To get the "filtering" you want, don't do a comparison to a string literal. Instead, do the comparison to an expression that has DATE datatype.
You can use the Oracle TO_DATE function. And you don't want to rely on setting of NLS_DATE_FORMAT, explicitly specify the format model as the second argument to the function. For example:
DO THIS
where entity.lt_date >= TO_DATE('2000-01-01','YYYY-MM-DD')
DON'T DO THIS
It's also possible to specify the format model as the second argument to the TO_CHAR function.
where TO_CHAR(entity.lt_date,'YYYY-MM-DD') >= '2001-01-01'
But you don't want to do that because that's going to force Oracle to evaluate that expression on the left side for every flipping row in the table, so it has a string value to do the comparison. (That's true unless someone created a function-based index for you.) If you do the comparison on the bare column, using the TO_DATE on the literal side, Oracle can make effective use of an appropriate index (with lt_date as the leading column) to satisfy the predicate.

How to take differece between 2 dates of different format in SQL

I have a table with a LOAD_STRT_DTM colum. This is a date column and values are like this - 18-JUL-14 08.20.34.000000000 AM.
I want to find the data which came before 5 days.
My logic is -
Select * from Table where 24 *(To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY')) >120
The issue is -
Select (To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY')) from table
This query should give the NumberOfDays between two dates. But this is not working, I Doubt, the issue is because of the format of the LOAD_STRT_DTM colum.
Please let me know where i am doint it wrong.
If your column is DATE datatype everything is ok, just shoot an:
select * from table where LOAD_STRT_DTM > sysdate - 5;
No need to convert dates to DATE datatype.
(To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY'))
You don't have to convert a DATE into a DATE again. IT is already a DATE. You just need to use it for date calculations. You use TO_DATE to convert a STRING into a DATE.
For example, if you have a string value like '18-JUL-14', then you would need to convert it into date using TO_DATE. Since your column is DATE data type, you just need to use as it is.
This is a date column
I want to find the data which came before 5 days.
Simply use the filter predicate as:
WHERE load_strt_dtm > SYSDATE - 5;
NOTE : SYSDATE has both date and time elements, so it will filter based on the time too. If you want to use only the date part in the filter criteria, then you could use TRUNC. IT would truncate the time element.
I have answered a similar question, have a look at this https://stackoverflow.com/a/29005418/3989608
It looks like LOAD_STRT_DTM is a TIMESTAMP rather than a DATE, given the number of decimal points following the seconds. The only thing you have to be cautious about is that Oracle will convert a DATE to a TIMESTAMP implicitly where one of the operands is a TIMESTAMP. So the solution
WHERE load_strt_dtm > SYSDATE - 5
will work; as will
WHERE load_strt_dtm + 5 > SYSDATE
but the following will not:
WHERE SYSDATE - load_start_dtm < 5
the reason being that TIMESTAMP arithmetic produces an INTERVAL rather than a NUMBER.
first convert two dates to same format select datediff(dd,convert(varchar(20),'2015-01-01',112),convert(varchar(20),'01-10-2015',112))