Converting date format number to date and taking difference in SQL - sql

I have a data set as below,
Same is date in "YYYYMMDD" format, I wanted to convert the columns to date format and take the difference between the same.
I used to below code
SELECT to_date(statement_date_key::text, 'yyyymmdd') AS statement_date,
to_date(paid_date_key::text, 'yyyymmdd') AS paid_date,
statement_date - paid_date AS Diff_in_days
FROM Table
WHERE Diff_in_days >= 90
;
Idea is to convert both the columns to dates, take the difference between them and filter cases where difference in days is more than 90.
Later I was informed that server is supported by HiveSQL and does not support of using ":", date time, and temp tables can not be created.
I'm currently stuck on how to go about given the constraints.
Help would be much appreciated.
Sample date for reference is provided in the link
dbfiddle

Hive is a little convoluted in its use of dates. You can use unix_timestamp() and work from there:
SELECT datediff(to_date(unix_timestamp(cast(statement_date_key as varchar(10)), 'yyyyMMdd')),
to_date(unix_timestamp(cast(paid_date_key as varchar(10)), 'yyyyMMdd'))
) as diff_in_days
FROM Table;
Note that you need to use a subquery if you want to use diff_in_days in a where clause.
Also, if you have date keys, then presumably you also have a calendar table, which should make this much simpler.

Hello You Can Use Below Query It Work Well
select * from (
select convert(date, statement_date_key) AS statement_date,
convert(date, paid_date) AS paid_date,
datediff(D, convert(date, statement_date_key), convert(date, paid_date)) as Diff_in_days
from Table
) qry
where Diff_in_days >= 90

Simple way: Function unix_timestamp(string, pattern) converts string in given format to seconds passed from unix epoch, calculate difference in seconds then divide by (60*60*24) to get difference in days.
select * from
(
select t.*,
(unix_timestamp(string(paid_date_key), 'yyyyMMdd') -
unix_timestamp(string(statement_date_key), 'yyyyMMdd'))/86400 as Diff_in_days
from Table t
) t
where Diff_in_days>=90
You may want to add abs() if the difference can be negative.
One more method using regexp_replace:
select * from
(
select t.*,
datediff(date(regexp_replace(string(paid_date_key), '(\\d{4})(\\d{2})(\\d{2})','$1-$2-$3')),
date(regexp_replace(string(statement_date_key), '(\\d{4})(\\d{2})(\\d{2})','$1-$2-$3'))) as Diff_in_days
from Table t
) t
where Diff_in_days>=90

Related

SQL difference between two datetime columns

I have a dataset with 2 columns of datetime datatype as shown here:
I want to take the difference between the two dates and I try it with this code:
Select
*,
original_due_date - due_date as difference
from
Table
However I'm not sure if the same would suffice as this is a datetime and not just date.
Any inputs would be much appreciated.
Desired output
The question was originally tagged Postgres, so this answers the original question.
Presumably, you are storing the values as timestamps. If you just want the results in days, then convert to dates and take the difference:
Select t.*,
(t.original_due_date::date - t.due_date::date) AS difference
from Table t;
If you want fractional days, then a pretty simple method is to extract the "epoch", which is measured in seconds, and use arithmetic:
Select t.*,
( extract(epoch from t.original_due_date -
extract(epoch from t.due_date
) / (24.0 * 60 * 60) AS decimal_days
from Table t;
transform timestamps to seconds (unix_timestamp), calculate difference and divide by (60*60*24) to get days
select (unix_timestamp(original_due_date, 'MM-dd-yyyy HH:mm')-unix_timestamp(due_date, 'MM-dd-yyyy HH:mm'))/(60*60*24) as difference_days
from (select '07-01-2021 00:00' as due_date, '02-10-2020 00:00' as original_due_date) t
Result:
-507

Retrieve mean time between failure within given date range parameter

Below is what i have tried,
select machine_id, count(incident_id) "No_Incident",
(fail_date BETWEEN (24 * to_date('&From_date_', 'DDMMYYYY') AND to_date('&To_Date','DDMMYYYY') / count(incident_id))) "MTBF"
from mytable;
This will work for you:
SELECT machine_id, count(incident_id) "No_Incident",
MAX(ROUND((ABS((TO_DATE('01-02-2019','DD-MM-YYYY') -
TO_DATE('03-02-2019'||' 23:59:59','DD-MM-YYYY HH24:MI:SS'))*24))))
/count(incident_id) AS MTBF
FROM
mytable;
You may consider the following examples:
since machine_id is not being aggregated (eg. being counted), I have used the group by to provide the Mean Time Between failure (MTBF) for each machine. If you would like for all machines, simple remove machine_id from the SELECT clause and the GROUP BY machine_id
You had a syntax error with your query as you were querying the range of dates using the between in your select clause. NB. I have modified this and placed it in a where clause. Based on how you execute your query (eq sql clients), how you may handle parameters may differ.
Using Oracle
SELECT
machine_id,
count(incident_id) as "No_Incidents",
(
EXTRACT(
HOUR FROM
CAST(MAX(fail_date) AS TIMESTAMP) - CAST(MIN(fail_date) AS TIMESTAMP)
) +
EXTRACT(
DAY FROM
CAST(MAX(fail_date) AS TIMESTAMP) - CAST(MIN(fail_date) AS TIMESTAMP)
) * 24
)/count(incident_id) as "MTBF"
FROM
mytable
WHERE
fail_date BETWEEN to_date('&From_date_', 'DDMMYYYY') AND to_date('&To_Date','DDMMYYYY')
GROUP BY
machine_id
In the oracle example, I converted the dates using CAST to a TIMESTAMP before finding the difference (date_max - date_min gives a date interval ). Extracting (using EXTRACT) and summing the hours (hours and days*24) gives the total hours.
Using MySQL
SELECT
machine_id,
count(incident_id) as "No_Incidents",
(
TIMESTAMPDIFF(HOUR,min(fail_date),max(fail_date))
)/count(incident_id) as "MTBF"
FROM
mytable
WHERE
fail_date BETWEEN to_date('&From_date_', 'DDMMYYYY') AND to_date('&To_Date','DDMMYYYY')
GROUP BY
machine_id
I have also used the TIMESTAMPDIFF in MYSQL function to determine the difference between the dates in hours.

Convert SQL Server code to Oracle please?

Having a bit of a issue with a SQL conversion from SQL Server to Oracle.
We are passing in a datetime value (in this example just 1900-01-01) and we need to select all rows that have a modified date greater than 2 days before the date passsed in. Here is the SQL syntax that works:
SELECT *
FROM TABLENAME
WHERE CAST(LAST_MODIFIED AS DATE) > CAST(DATEADD(dd, -2, '1990-01-01') AS DATE);
Where LAST_MODIFIED is a column, and the '1900-01-01' is a value being injected to the SQL String in C# prior to it being executed. Before being asked, we prefer not to subtract the 2 days from the date before passing it to the SQL :)
So what we need then is just the above query converted to Oracle syntax... We have tried a couple things and it fails :(
Thanks,
Dave
You can write this in Oracle as:
SELECT *
FROM TABLENAME
WHERE TRUNC(LAST_MODIFIED) > (DATE '1990-01-01') - 2
Notes:
In Oracle, DATE includes a time component, so casting to a date does nothing.
Oracle supports various ways to include a date/time constant. I prefer the keyword DATE with the ISO/ANSI standard date format YYYY-MM-DD.
The - 2 is perhaps more accurately written as - interval '2' day. However, the interval notation is new(ish) to Oracle.
And, it is better in either database to write this without modifying last_modified_date:
SELECT *
FROM TABLENAME
WHERE LAST_MODIFIED >= (DATE '1990-01-01') - 1
Removing the time component is not needed, with the right date comparison.
SELECT *
FROM TABLENAME
WHERE CAST(LAST_MODIFIED AS DATE) > TO_DATE('1990-01-01','YYYY-MM-DD')-2;
SELECT *
FROM TABLENAME
WHERE TRUNC( LAST_MODIFIED ) > TO_DATE( '1990-01-01', 'YYYY-MM-DD' ) - 2;
or, if you pass the value in using the :date_value bind variable:
SELECT *
FROM TABLENAME
WHERE TRUNC( LAST_MODIFIED ) > :date_value - 2;
If the value you are passing in to the query does not have a time component then you can just do:
SELECT *
FROM TABLENAME
WHERE LAST_MODIFIED >= :date_value - 1;

How to convert Date-time into Date using Netezza

I am doing some calculation but my calculation is off because my date field is showing the time-stamp and i only want to use as Date only when i am doing the calculation. How can i just ignore the minutes and just use the date when doing the calculation? Here is what i have:
SELECT EF.DSCH_TS,
CASE WHEN EXTRACT (DAY FROM EF.DSCH_TS - EF.ADMT_TS)>=0 THEN 'GroupA' END AS CAL
FROM MainTable EF;
Netezza has built-in function for this by simply using:
SELECT DATE(STATUS_DATE) AS DATE,
COUNT(*) AS NUMBER_OF_
FROM X
GROUP BY DATE(STATUS_DATE)
ORDER BY DATE(STATUS_DATE) ASC
This will return just the date portion of the timetamp and much more useful than casting it to a string with TO_CHAR() because it will work in GROUP BY, HAVING, and with other netezza date functions. (Where as the TO_CHAR method will not)
Also, the DATE_TRUNC() function will pull a specific value out of Timestamp ('Day', 'Month, 'Year', etc..) but not more than one of these without multiple functions and concatenate.
DATE() is the perfect and simple answer to this and I am surprised to see so many misleading answers to this question on Stack. I see TO_DATE a lot, which is Oracle's function for this but will not work on Netezza.
With your query, assuming that you're interested in the days between midnight to midnight of the two timestamps, it would look something like this:
SELECT EF.DSCH_TS,
CASE
WHEN EXTRACT (DAY FROM (DATE(EF.DSCH_TS) - DATE(EF.ADMT_TS)))>=0 THEN 'GroupA'
END AS CAL
FROM MainTable EF;
You may want to consider rewriting your case statement to return an interval. This will allow for a little more flexibility.
SELECT EF.DSCH_TS,
CASE
WHEN age(date(EF.DSCH_TS),date(EF.ADMT_TS))>= interval '6 days'
THEN 'GroupA' END AS CAL
FROM MainTable EF;
Use date_trunc() with the first argument of 'day'. I think this is what you want:
SELECT EF.DSCH_TS,
(case when date_trunc('day', EF.DSCH_TS) >= date_trunc('day', EF.ADMT_TS) THEN 'GroupA' END) AS CAL
FROM MainTable EF;

Select from table by knowing only date without time (ORACLE)

I'm trying to retrieve records from table by knowing the date in column contains date and time.
Suppose I have table called t1 which contains only two column name and date respectively.
The data stored in column date like this 8/3/2010 12:34:20 PM.
I want to retrieve this record by this query for example (note I don't put the time):
Select * From t1 Where date="8/3/2010"
This query give me nothing !
How can I retrieve date by knowing only date without the time?
DATE is a reserved keyword in Oracle, so I'm using column-name your_date instead.
If you have an index on your_date, I would use
WHERE your_date >= TO_DATE('2010-08-03', 'YYYY-MM-DD')
AND your_date < TO_DATE('2010-08-04', 'YYYY-MM-DD')
or BETWEEN:
WHERE your_date BETWEEN TO_DATE('2010-08-03', 'YYYY-MM-DD')
AND TO_DATE('2010-08-03 23:59:59', 'YYYY-MM-DD HH24:MI:SS')
If there is no index or if there are not too many records
WHERE TRUNC(your_date) = TO_DATE('2010-08-03', 'YYYY-MM-DD')
should be sufficient. TRUNC without parameter removes hours, minutes and seconds from a DATE.
If performance really matters, consider putting a Function Based Index on that column:
CREATE INDEX trunc_date_idx ON t1(TRUNC(your_date));
Personally, I usually go with:
select *
from t1
where date between trunc( :somedate ) -- 00:00:00
and trunc( :somedate ) + .99999 -- 23:59:59
Convert your date column to the correct format and compare:
SELECT * From my_table WHERE to_char(my_table.my_date_col,'MM/dd/yyyy') = '8/3/2010'
This part
to_char(my_table.my_date_col,'MM/dd/yyyy')
Will result in string '8/3/2010'
You could use the between function to get all records between 2010-08-03 00:00:00:000 AND 2010-08-03 23:59:59:000
trunc(my_date,'DD') will give you just the date and not the time in Oracle.
Simply use this one:
select * from t1 where to_date(date_column)='8/3/2010'
Try the following way.
Select * from t1 where date(col_name)="8/3/2010"