Difference between two timestamp in Hive through query - hive

I have a hive table with following columns
session Timestamp
1 2018-05-18T00:00:00.000Z
1 2018-05-18T00:01:00.000Z
1 2018-05-18T00:02:00.000Z
1 2018-05-18T00:03:00.000Z
2 2018-05-18T00:05:00.000Z
2 2018-05-18T00:10:00.000Z
2 2018-05-18T00:15:00.000Z
For each session, I want to find the difference between the first timestamp and last timestamp, in seconds
Hence my output will be like this
session Period
1 180
2 600
The 1st difference, 180 (seconds) = 2018-05-18T00:03:00.000Z - 2018-05-18T00:00:00.000Z
The 2nd difference, 600 (seconds) = 2018-05-18T00:15:00.000Z - 2018-05-18T00:05:00.000Z
Both session and Timestamp is in string.
I am trying to convert string timestamp into unix timestamp using this command, however I am not successful
select from_unixtime(unix_timestamp(Timestamp, "yyyy-MM-dd'T'HH:mm:ss.SSSZ")) AS NEW_TIMESTAMP from TBL;

unix_timestamp converts a string to timestamp (seconds), so you just need to use this function and substract the min from the max :
select
max(unix_timestamp(Timestamp, "yyyy-MM-dd'T'HH:mm:ss.SSSZ"))
-
min(unix_timestamp(Timestamp, "yyyy-MM-dd'T'HH:mm:ss.SSSZ"))
from TBL
group by session_id
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF

Related

Timestamp update DB2 SQL

I would like to update query for records between 24 hours since the specific date and time. The current query works fine, except I need to update two timestamps manually. I am looking to reduce timestamps number to one or replace it with dynamic expression, so it will minimize human error if possible.
Current query looks like this:
SELECT timestamp
FROM table
WHERE timestamp BETWEEN '2023-01-18-06.00.00.000000' AND '2023-01-19-06.00.00.000000'
I have been trying multiple recommended options but it does not work yet:
WHERE timestamp > '2023-01-19-06.00.00.000000' - 24 HOURS
WHERE timestamp > '2023-01-19-06.00.00.000000' – ‘24 HOURS’
WHERE timestamp ('2023-01-19-06.00.00.000000' - 24 HOURS)
WHERE timestamp > '2023-01-19-06.00.00.000000' - '24.00.00.000000'
WHERE timestamp BETWEEN '2023-01-04-06.00.00.000000' AND INTERVAL - 24 HOURS
WHERE timestamp > CURRENT DATE - 24 HOURS
WHERE timestamp ('2023-01-19' - 1 DAY, ('06.00.00.000000' - 24 HOURS))
Could anyone let me know what I am doing incorrectly?
'2023-01-19-06.00.00.000000' - 24 HOURS is near, but incorrect because DB2 doesn't see the first value as a timestamp but as a string even if it makes the automatic cast in the working query. so what you have to do is to tell it is a timestamp, because you add a duration
with the timestamp keyword
WHERE yourtimestamp > timestamp '2023-01-19-06.00.00.000000' - 24 HOURS
or the timestamp function
WHERE yourtimestamp > timestamp('2023-01-19-06.00.00.000000') - 24 HOURS
or this notation
WHERE yourtimestamp > '2023-01-19-06.00.00.000000'::timestamp - 24 HOURS
if you're not using DB2LUW or an old version, one or more option may not be available
i suggest you try something like this
SELECT timestamp
FROM table cross join (values timestamp '2023-01-19-06.00.00.000000') as ref (stamp)
WHERE timestamp between ref.stamp - 24 hours and ref.stamp
For the past 24hrs, as implied by your example
WHERE timestamp > CURRENT DATE - 24 HOURS
You'd want to use CURRENT TIMESTAMP not CURRENT DATE
For a specific period, you'll always need two dates specified in the WHERE clause like so
WHERE timestamp BETWEEN startTs AND endTs
For a specific 24hr period from a given starting timestamp, you can do something like so:
WHERE timestamp BETWEEN startTs AND startTs + 24 hours
You can define startTs as a global variable, and use it in your select
create variable startTs timestamp default('2023-01-18 06:00:00.000');
SELECT timestamp
FROM table
WHERE timestamp BETWEEN startTs AND startTs + 24 hours;
Or you could use a table value constructor to store it for use...
WITH tmp (startTime) AS (
VALUES (timestamp('2023-01-19 06:00:00.000'))
)
select timestamp from table
where timestamp between (select startTime from tmp limit 1)
and (select startTime + 2 hours from tmp limit 1);
Depending on your use case, it might be worthwhile to encapsulate the statement as a stored procedure or a user defined table function (UDTF)...

How to get 24 hours back time from current time in Oracle

I have a column in my Oracle db which records the creation time of a user in the following format
30-NOV-20 11.49.11.000000000 AM (TIMESTAMP(6) format).
What I wanted to do is select all records whose creation time is 24 hours earlier than current time
So what I was going to do was subtract 1 from current time and compare it. But when I subtract 1 it returns only the date.
select * from user where created_date < SYSTIMESTAMP-1
dbms_output.put_line (SYSTIMESTAMP-1);-->29-NOV-20
The time parts are missing which makes me unable to compare with created time in the table
Please help me to complete this task.
If you subtract 1 from a date datatype (e.g. sysdate), it'll move you back one day. But, if you subtract it from a timestamp datatype value, Oracle will convert it to date and return a date (moreover, it'll be truncated).
See the following example:
SQL> select
2 systimestamp val1,
3 systimestamp - 1 val2,
4 --
5 systimestamp - interval '1' day val3
6 from dual;
VAL1
-----------------------------------------------------
VAL2
--------
VAL3
-----------------------------------------------------
30.11.20 09:55:01,439352 +01:00
29.11.20
29.11.20 09:55:01,439352000 +01:00
SQL>
So, what you should do is to subtract an interval, i.e.
select *
from user
where created_date < systimestamp - interval '1' day;
Half the problem is that whatever client program is being used to display the values is using the default date format for their territory and that default format is set to DD-MON-RR.
You can change the NLS_DATE_FORMAT and NLS_TIMESTAMP_FORMAT session parameters and that will (assuming your client program uses them and not some internal settings) give you the output you are expecting:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF9';
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF9TZR';
Then
SELECT SYSDATE, SYSTIMESTAMP FROM DUAL;
Outputs (depending on your system time zone):
SYSDATE | SYSTIMESTAMP
:------------------ | :----------------------------------
2020-11-30 10:12:22 | 2020-11-30 10:12:22.476282000+00:00
If you use SYSTIMESTAMP-1 then Oracle does not support subtracting a NUMBER data type from a TIMESTAMP [WITH TIME ZONE] data type but it does support subtracting a NUMBER data type from a DATE data type and will perform an implicit cast from TIMESTAMP to DATE so that the query is valid.
For example:
SELECT SYSDATE - 1, SYSTIMESTAMP - 1, SYSTIMESTAMP - INTERVAL '1' DAY FROM DUAL;
Outputs:
SYSDATE-1 | SYSTIMESTAMP-1 | SYSTIMESTAMP-INTERVAL'1'DAY
:------------------ | :------------------ | :----------------------------------
2020-11-29 10:24:02 | 2020-11-29 10:24:02 | 2020-11-29 10:24:02.651735000+00:00
You can see that in the middle column SYSTIMESTAMP-1 gives the same output as SYSDATE-1 but in the right-hand column, subtracting an interval has ensured that TIMESTAMP WITH TIME ZONE data type is maintained.
So your query:
SELECT * FROM user WHERE created_date < SYSTIMESTAMP-1
Is effectively:
SELECT * FROM user WHERE created_date < CAST( SYSTIMESTAMP AS DATE )-1
Which will have exactly the same year, month, day, hour, minute and (integer) second components but will lose the fractional seconds and time zone information from the SYSTIMESTAMP.
If your column does not have time zone data and the level of precision in the fractional seconds does not matter to you then your query will work adequately.
However, if you want to keep the time zone and/or fractional seconds information then you can use:
SELECT * FROM user WHERE created_date < SYSTIMESTAMP - INTERVAL '1' DAY;
However, if created_date is a DATE column, you probably want:
SELECT * FROM user WHERE created_date < SYSDATE - INTERVAL '1' DAY;
or
SELECT * FROM user WHERE created_date < SYSDATE - 1;
db<>fiddle here
You can use it as (SYSDATE, -1).
Also, if you want to search for new records within 24 hours, it should be "created_date> = (sysdate-1)".

postgresql 8.0 fetch start of hour based on timestamp

I am using postgresql 8.0 wherein I have a column which is a timestamp in milliseconds from epoch (but stored as text in table). I want to identify the start of hour for this timestamp. I am unable to think of clean way to do
Table structure
id (varchar(52)) | Name(varchar(100)) | UpdateTime (varchar(20))
1 | Robin | 1598051512000
2 | Sally | 1628734800000
My thought process was to use to_timestamp(). However it does not accept a BigInt. So the idea was to use substring() to discard the last 3 characters of the value in updateTime and then pass it to to_timestamp()
e.g. using select substring('1598051512000', 1, length('1598051512000') - 3));
However this seems to be getting convoluted. IS there a cleaner way to get start of hour based on timestamp?
Expected Output for input
1598051512000 = 2020-08-21T23:00:00Z
1628734800000 = 2020-08-12T02:00:00Z
You could use date arithmetics, then date_trunc():
select
t.*,
date_trunc(
'hour',
date '1970-01-01' + '1598051512000'::bigint / 1000 * '1 second'::interval
) UpdateHour
from mytable t

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');