how to get Date difference in postgres with date part - sql

How to get datetime difference in postgres
I am using below syntax
DATE_PART('hour', A_column::timestamp-B_column::timestamp )
I want output like this:
If A_column=2020-05-20 00:00:00 and B_column=2020-05-15 00:00:00 I want to get 72(in hours).
Is there any possibility to skip weekends(Saturday and Sunday) in first one, it means to get the result as 72 hours(exclude weekend hours)
If A_column=2020-08-15 12:00:00 and B_column=2020-08-15 00:00:00 I want to get 12(in hours).

You could write this as:
select extract(epoch from a_column::timestamp - b_column::timestamp) / 60 / 60
from mytable
Rationale: substracting the two timestamps gives you an interval; you can then turn it to a number of seconds, and do arithmetics to convert that to hours.

Related

SQL - Creating UTC Timestamp from separate date/time/timezone information

I'm working with BigQuery and have a table that looks like:
YEAR
MONTH
DAY
timezone
local time
2015
6
24
America/Los Angeles
1930
Where local time is given by hhmm. I'm wondering if I can format this information into a timestamp column in SQL that yields time in UTC.
I know I can use `TO_TIMESTAMP` but that would involve concatenating all these columns as strings first. Is there any better way to do this? If I were to concatenate, I'm not sure how I would use timezone and then back out UTC.
You might consider below.
WITH sample_table AS (
SELECT 2015 year, 6 month, 24 day, 'America/Los_Angeles' timezone, 1930 local_time UNION ALL
SELECT 2015 year, 6 month, 24 day, 'America/Los_Angeles' timezone, 2400 local_time
)
SELECT TIMESTAMP_SECONDS(
UNIX_SECONDS(TIMESTAMP(DATE(year, month, day), timezone))
+ DIV(local_time, 100) * 3600 + MOD(local_time, 100) * 60
) utc
FROM sample_table;
Since TIME(24, 0, 0) is not a valid time format, the query converts datetime into unix seconds and get back to UTC with the time calculation in seconds.
Input calculates to invalid time: 24:00:00
Query results

Presto SQL / Athena: select between times across different days

I have a database that contains a series of events and their timestamp.
I find myself needing to select all events that happen between 11:00 and 11:10 and 21:00 and 21:05, for all days.
So what I would do is I extract from timestamp the hour and the minute, and:
SELECT *
WHERE (hour = 11 AND minute <= 10)
OR (hour = 21 AND minute <= 05)
However, I was wondering if there's a simpler / less verbose way to do this, such as when you query between dates:
SELECT *
WHERE date BETWEEN '2020-07-01' AND '2020-07-05'
I read here that this is doable in SQLite, I was wondering if it's possible to be done in presto as well. I've looked at the docs but couldn't find an analogue function that does what time() does in SQLite.
You could use date formatting functions, e.g. date_format, then string comparisons:
select *
from mytable
where
date_format(mydate, '%H:%i') between '11:00' and '11:09'
or date_format(mydate, '%H:%i') between '21:00' and '21:04'
Note that I substracted one minute from the upper bound, since I assume you don't want to include the last minute. between '11:00' and '11:09' gives you everything from 11:00:00 to 11:09:59.

How to subtract hours and minutes from each other in PostgreSQL

I have two fields dateTS and closingTime.
dateTS is a normal timestamp field (e.g. 2019-07-13 22:31:10.000000)
closingTime is a HH:MM format of when a store closes (e.g. 23:00)
I need a PostgreSQL query to subtract the two field and get the number of minutes difference between them.
Using the examples given above the difference between the two fields would be 28 minutes
So far I've tried different variations of the datediff function, but it won't work.
My guess is I either have to
a. generate a fake timestamp for closingTime which is the same day as the dateTs field and subtract the 2 timestamps.
or
b. convert the hour/minutes of both field to a float and subtract the two values to get the hours difference and convert that to minutes
You can just subtract them by converting the timestamp to a time:
select closingtime - datets::time
from your_table;
That will give you an interval as the result.
To convert that to minutes you can get the number of seconds and divide it by 60:
select (extract epoch from closingtime - datets::time) / 60
from your_table;
Cast your closing time to an interval and the timestamp to time and then subtract the two. By casting the timestamp to time you are effectively discarding the date part. You can the subtract one from the other to generate the difference as an interval.
select closingTime::interval - dateTS::time...
e.g.:
# select '23:00'::interval - now()::time;
?column?
-----------------
05:31:00.031141
(1 row)
If needed you can then convert the interval to minutes:
# select extract(epoch from ('23:00'::interval - now()::time)) / 60;
?column?
------------------
327.435313083333
(1 row)

Time Difference in Redshift

how to get exact time Difference between two column
eg:
col1 date is 2014-09-21 02:00:00
col2 date is 2014-09-22 01:00:00
output like
result: 23:00:00
I am getting result like
Hours Minutes Seconds
--------------------
3 3 20
1 2 30
using the following query
SELECT start_time,
end_time,
DATE_PART(H,end_time) - DATE_PART(H,start_time) AS Hours,
DATE_PART(M,end_time) - DATE_PART(M,start_time) AS Minutes,
DATE_PART(S,end_time) - DATE_PART(S,start_time) AS Seconds
FROM user_session
but i need like
Difference
-----------
03:03:20
01:02:30
Use DATEDIFF to get the seconds between the two datetimes:
DATEDIFF(second,'2014-09-23 00:00:00.000','2014-09-23 01:23:45.000')
Then use DATEADD to add the seconds to '1900-01-01 00:00:00':
DATEADD(seconds,5025,'1900-01-01 00:00:00')
Then CAST the result to a TIME data type (note that this limits you to 24 hours max):
CAST('1900-01-01 01:23:45' as TIME)
Then LTRIM the date part of the value off the TIME data (as discovered by Benny). Redshift does not allow use of TIME on actual stored data:
LTRIM('1900-01-01 01:23:45','1900-01-01')
Now, do it in a single step:
SELECT LTRIM(DATEADD(seconds,DATEDIFF(second,'2014-09-23 00:00:00','2014-09-23 01:23:45.000'),'1900-01-01 00:00:00'),'1900-01-01');
:)
SELECT LTRIM(DATEADD(seconds,DATEDIFF(second,'2014-09-23 00:00:00','2014-09-23 01:23:45.000'),'1900-01-01 00:00:00'),'1900-01-01');

Oracle: subtract millisecond from a datetime

I thought it was really simple but it isn't.
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY')
- 1/(24*50*60*1000) data
FROM dual;
It simply doesn't work.
Other details:
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') -
NUMTODSINTERVAL(1/(24*50*60*1000),'HOUR') data
FROM dual;
doesn't work..
The right seems to be
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') -
NUMTODSINTERVAL(1/(24*25*60*1000),'HOUR') data
FROM dual;
Why? How does it work?
For adding or subtracting an amount of time expressed as a literal you can use INTERVAL.
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY')
- INTERVAL '0.001' SECOND
FROM dual;
As well there are now standard ways to express date and time literals and avoid the use of various database specific conversion functions.
SELECT TIMESTAMP '2012-10-08 00:00:00'
- INTERVAL '0.001' SECOND DATA
FROM dual;
For your original question the time part of a day is stored in fractional days. So one second is:
1 / (hours in day * minutes in hour * seconds in a minute)
Divide by 1000 to get milliseconds.
1 / (24 * 60 * 60 * 1000)
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') - NUMTODSINTERVAL(1/(24*50*60*1000),'HOUR') data
FROM dual;
OUTPUT
DATA
---------------------------------
09/AUG/12 11:59:59.999950000 PM
1 row selected.
The answer posted above subtracts a tenth of a millisecond from the date. I think what you want is the following:
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY')-NUMTODSINTERVAL(1/1000,'SECOND')
FROM dual;
Output:
DATA
---------------------------------------------------------------------------
09-AUG-12 11.59.59.999000000 PM
^^^
|||
tenths|thousandths
|
hundredths
The following NUMTODSINTERVAL(1/(24*25*60*1000),'HOUR') seems to work only because 24*25 = 600. But that number is wrong because 1/(600*60*1000) of an hour is a tenth of a millisecond, not a millisecond. If you want to use 'HOUR' in NUMTODSINTERVAL() you should use 1/(60*60*1000) (sixty minutes in an hour, sixty seconds in a minute, 1000 ms in a second).
This is correct (with a millisecond being 1000th of a second):-
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') - NUMTODSINTERVAL(1/1000,'SECOND') data FROM dual;
DATA
-----------------------------
09-AUG-12 23.59.59.999000000
As to why the other code isn't working it's because you aren't calculating a millisecond correctly. An hour must be divided by 60 to give minutes and again by 60 to given seconds then by 1000 to give a millisecond, thus if you must use HOUR as the interval then it is:-
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') - NUMTODSINTERVAL(1/(60*60*1000),'HOUR') as data FROM dual;
DATA
---------------------------------------------------------------------------
09-AUG-12 23.59.59.999000000
select TO_CHAR(TO_TIMESTAMP('10.05.2012', 'DD.MM.YYYY') -
NUMTODSINTERVAL(1/1000, 'SECOND'), 'DD.MM.YYYY HH24:MI:SS:FF3') Res
from dual;
RES
-----------------------------
09.05.2012 23:59:59.999