Time Difference between two time columns in sql server - sql

I have the issue in getting the minutes difference between two time columns in sql server.
Column1: Starttime
Column2: Endtime
These two are of the type nchar(10) , I converted them into time format in the below way and using the datediff function.
If the two columns have AM format or PM format, then difference of minutes is coming fine. But if i have start time is in PM format and End time as AM (SQL taking it as next day) format then i am getting negative minutes than expected.
select
dty_act_start_time,
dty_act_end_time,
datediff(minute, convert(varchar,dty_act_start_time,114),convert(varchar,dty_act_end_time,114))
from DB.Mydatabase;
Please let me know how to get the correct difference in minutes.

Just add 1440 minutes (number of minutes in 24 hours) if start time is greater than end time:
select
start_time_time,
end_time_time,
datediff(minute, start_time_time, end_time_time) + iif(start_time_time <= end_time_time, 0, 1440) as diff
from (
select
convert(time(0), dty_act_start_time, 114) as start_time_time,
convert(time(0), dty_act_end_time, 114) as end_time_time
from (values
('09:00am', '10:00pm'),
('10:00pm', '09:00am')
) tests(dty_act_start_time, dty_act_end_time)
) x
Result:
start_time_time | end_time_time | diff
09:00:00 | 22:00:00 | 780
22:00:00 | 09:00:00 | 660

Related

How do I calculate the difference between two timestamps?

How to calculate the difference in minutes between timestamps TIMEIN and TIMEOUT? My table (only 3 rows):
DATE
TIMEIN
TIMEOUT
2020-05-06
14:00
15:00
2020-05-06
14:45
15:55
2020-05-07
09:00
10:45
My SQL doesn't output what I want:
SELECT (T.DATE + T.TIMEIN - T.DATE + T.TIMEOUT) AS `Duration`
FROM Transport T;
Output:
Duration
29
29
19
It should be :
Duration
60
70
105
I tried this without using the date, however that lead to an output of -1 for all rows.
Assuming that TIMEOUT is always greater than TIMEIN you can subtract the unix epochs of the 2 values and divide by 60 to get the number of minutes:
SELECT (strftime('%s', TIMEOUT) - strftime('%s', TIMEIN)) / 60 AS Duration
FROM Transport;
See the demo.
date/time is not like integers so they didn't add/subtract like integers. So convert them in a timestamp before subtraction.

incorrect date time format in Oracle DB, convert to hours and minutes

Don't ask me why but for some reason we have a date time column that is in the wrong format that I need help converting.
Example timestamp from DB: 01-OCT-20 12.18.44.000000000 AM
In the example above the hours is actually 18 and the minutes is 44.
Not sure how this happened by 12 is the default for everything. All I want to do is get the difference in HH:MM from 2 timestamps, but i dont know how to convert this properly with the hours being in the minute section and the minutes being in the seconds section.
Example of what I'm looking for:
01-OCT-20 12.18.44.000000000 AM - 01-OCT-20 12.12.42.000000000 AM
Output: 06:02 . so the timespan would be 6 hours and 2 minutes in this case.
Thanks,
In the example above the hours is actually 18 and the minutes is 44.
Not sure how this happened by 12 is the default for everything. All I want to do is get the difference in HH:MM from 2 timestamps, but i dont know how to convert this properly with the hours being in the minute section and the minutes being in the seconds section.
To convert minutes to hours, you need to multiply by 60.
To convert seconds to minutes, you also need to multiply by 60.
So, if you want to convert the time part of the correct value then you take the time since midnight and multiply it all by 60.
If you want to get the difference between the current and correct time (after multiplying by 60) then you want to subtract the current time (which can be simplified to just multiplying by 59).
So to get the time difference you can use:
SELECT (value - TRUNC(value))*59 AS difference,
value + (value - TRUNC(value))*59 AS updated_value
FROM table_name;
So, for your sample data:
CREATE TABLE table_name ( value ) AS
SELECT TO_TIMESTAMP( '01-OCT-20 12.18.44.000000000 AM', 'DD-MON-RR HH12.MI.SS.FF9 AM' ) FROM DUAL
Then the output is:
DIFFERENCE | UPDATED_VALUE
:---------------------------- | :-------------------------
+000000000 18:25:16.000000000 | 2020-10-01 18:44:00.000000
db<>fiddle here
If you want to compare two wrong values just subtract one timestamp from the other and multiply by 60 (assuming that the hour will always be 12 AM or 00 in the 24 hour clock):
SELECT (value1 - value2) * 60 AS difference,
value1,
value1 + (value1 - TRUNC(value1))*59 AS updated_value1,
value2,
value2 + (value2 - TRUNC(value2))*59 AS updated_value2
FROM table_name;
So, for the sample data:
CREATE TABLE table_name ( value1, value2 ) AS
SELECT TO_TIMESTAMP( '01-OCT-20 12.18.44.000000000 AM', 'DD-MON-RR HH12.MI.SS.FF9 AM' ),
TO_TIMESTAMP( '01-OCT-20 12.12.42.000000000 AM', 'DD-MON-RR HH12.MI.SS.FF9 AM' )
FROM DUAL
The output is:
DIFFERENCE | VALUE1 | UPDATED_VALUE1 | VALUE2 | UPDATED_VALUE2
:---------------------------- | :------------------------- | :------------------------- | :------------------------- | :-------------------------
+000000000 06:02:00.000000000 | 2020-10-01 00:18:44.000000 | 2020-10-01 18:44:00.000000 | 2020-10-01 00:12:42.000000 | 2020-10-01 12:42:00.000000
Which gives the difference as 6 hours and 2 minutes.
db<>fiddle here

How to retrieve the min and max times of a timestamp column based on a time interval of 30 mins?

I am trying to pull a desired output that looks like this
Driver_ID| Interval_Start_Time | Interval_End_Time | Clocked_In_Time | Clocked_Out_Time | Score
232 | 2019-04-02 00:00:00.000 | 2019-04-02 00:30:00.000 | 2019-04-02 00:10:00.000 | 2019-04-02 00:29:00.000 | 0.55
My Goal is to pull the ID in 30 minute or per half hour time intervals, and their min or earliest clocked in time and max or latest clocked out time in that same 30 minute or half hour interval.
The query I have currently is
WITH TIME AS
(SELECT DISTINCT CASE
WHEN extract(MINUTE
FROM offer_time_utc)<30 THEN date_trunc('hour', offer_time_utc)
ELSE date_add('minute',30, date_trunc('hour', offer_time_utc))
END AS interval_start_time,
CASE
WHEN extract(MINUTE
FROM offer_time_utc)<30 THEN date_add('minute',30, date_trunc('hour', offer_time_utc))
ELSE date_add('hour',1, date_trunc('hour', offer_time_utc))
END AS interval_end_time
FROM integrated_delivery.trip_offer_fact offer
WHERE offer.business_day = date '2019-04-01' )
SELECT DISTINCT offer.Driver_ID,
offer.region_uuid,
interval_start_time,
interval_end_time,
min(sched.clocked_in_time_utc) AS clocked_in_time,
max(sched.clocked_out_time_utc) AS clocked_out_time,
cast(scores.acceptance_rate AS decimal(5,3)) AS acceptance_rate
FROM integrated_delivery.trip_offer_fact offer
JOIN TIME ON offer.offer_time_utc BETWEEN time.interval_start_time AND time.interval_end_time
JOIN integrated_delivery.courier_actual_hours_fact sched ON offer.Driver_ID = sched.Driver_ID
JOIN integrated_product.driver_score_v2 scores ON offer.Driver_ID = scores.courier_id
AND offer.region_uuid = scores.region_id
AND offer.region_uuid = sched.region_uuid
AND offer.business_day = date '2019-04-01'
AND sched.business_day = date '2019-04-01'
AND scores.extract_dt = 20190331
AND offer.region_uuid IN('930c534f-a6b6-4bc1-b26e-de5de8930cf9')
GROUP BY 1,2,3,4,7
But it does not seem to give me the correct min and max clocked in and clocked out time in that correct interval as below,
driver_uuid region_uuid interval_start_time interval_end_time clocked_in_time clocked_out_time score
232 bbv 2019-04-01 14:30:00.000 2019-04-01 15:00:00.000 2019-04-01 14:43:13.140 2019-04-01 22:30:46.043 0.173
When I add in these 2 lines,
JOIN TIME ON sched.clocked_in_time_utc BETWEEN time.interval_start_time AND time.interval_end_time
jOIN TIME ON sched.clocked_out_time_utc BETWEEN time.interval_start_time AND time.interval_end_time
iIt gives me an error as I dont think that is correct.
How can I correctly pull in the min and max clock in and clock out time for the correct interval? Meaning I only want the earliest clocked in time and the latest clocked out time in that per half hour interval start and end time.
I appreciate anybody looking ! Thanks

conversion of time into minute count

Ok so I need to convert a value from a table into an absolute minute count.
What I mean by that is this.
I currently have data like this
ID day time
1 1 00:04
2 1 01:08
3 2 00:08
4 2 02:04
I want it to convert to total count of minutes, not resettting back to zero for each day. so it would be
ID day time
1 1 04
2 1 68
3 2 1448
4 2 1564
Currently the time data is varchar(5) and not in date time. I have tried
DATEDIFF(MINUTE, DATEADD(DAY, DATEDIFF(DAY, 0,dispatchday), 0), dispatchday)
and that returned nothing but zero's
SQL Server I presume? This should take care of it. It doesn't make a difference what kind of field time is in, as long as it contains a valid time value.
select (day-1) * 1440 + datediff(minute, '00:00:00', time) as result from yourtable

T-SQL: Check temperature over 24 hour period

I have a SQL Server database with two values I'm interested in:
dtime - datetime
temperature - varchar
The table is fed by an external process that takes a building's temperature every 30 minutes. I'm interested in triggering an alert if the temperature exceeds 80 degrees for 48 periods (24 hours).
I think this needs to be an external process that scans the table and sends an alert when this condition is met. I'm struggling with writing the SQL to do this.
EDIT
The data I'm pulling in comes in on a weekly basis. During this week I need to see if at any time in a 24-hour period the temperature has exceeded 80 degrees. The air conditioning could fail at any time and span two days or more, so I need to potentially check this across multiple days. The temperature is taken every half hour, so during the week I need to check if there are 48+ instances where the temperature exceeded 80 degrees.
Sample data:
10/1/2012 12:00:00 AM | 70 | {ok}
10/1/2012 12:30:00 AM | 70 | {ok}
10/1/2012 1:00:00 AM | 70 | {ok}
10/1/2012 1:30:00 AM | 75 | {ok}
10/1/2012 2:00:00 AM | 75 | {ok}
10/1/2012 2:30:00 AM | 80 | {ok}
You can use ALL:
IF 80 < ALL(
SELECT temperature
FROM (
SELECT temperature, dtime,
RN = ROW_NUMBER() OVER (ORDER BY dtime DESC)
FROM dbo.Temps
) X
WHERE RN <= 48
)
SELECT 'ALERT, the last 48 measurements exceeded 80 degrees!'
ELSE
SELECT 'everything is okay';
Fiddle: http://sqlfiddle.com/#!6/4e2c8/7/0
Edit: As Blam has mentioned this can be simplified by using TOP
IF 80 < ALL(
SELECT TOP 48 temperature
FROM dbo.Temps
ORDER BY dtime DESC
)
SELECT 'ALERT, the last 48 measurements exceeded 80 degrees!'
ELSE
SELECT 'everything is okay';
select 'alert'
where not exists (
select 1
from MyTable
where dtime > dateadd(day, -1, getdate())
and cast(temperature as int) <= 80
)