Calculate duration from Times stored as Char(4) - sql

I am trying to calculate the duration of a service where the times in the table are stored as Char(4) HHMM. For example, the start time is 1402, which would be 14:02, and the end time is 1536, which would be 15:36.
I need it to return a duration of 94 minutes. When I tried to just convert to numeric and subtract I get 134. I have tried to convert to time, but every example I have tried gives me a conversion type message.

Just convert the value to a time, and then use DATEDIFF:
SELECT DATEDIFF(MINUTE, CONVERT(time,STUFF(StartTime,3,0,':')),CONVERT(time,STUFF(EndTime,3,0,':')))
FROM dbo.YourTable;

You can use string functions and arithmetics:
select t.*,
(left(starttime, 2) * 60 + right(starttime, 2) - left(endtime, 2) * 60 - left(endtime)) / 60 minutes_diff
from mytable t
This converts the strings to a number of seconds, substracts the values, then converts back to minutes.

You can convert the difference to minutes and then add that back to a zero time:
select convert(time,
dateadd(minute,
(((et / 100) * 60) + (et % 60)) - (((st / 100) * 60) + (st % 60)),
0)
)
from (values (1402, 1536)) v(st, et);
Here is a db<>fiddle.

Thank you everyone for the answers, but I found my answer!
DateDiff(Minute, try_cast(substring(c.start_time, 1, 2) + ':' + substring(start_time, 3, 2) as time),
try_cast(substring(stop_time, 1, 2) + ':' + substring(c.stop_time, 3, 2) as time))

Task: given two parametes as char(4)
1402, 1536 in format HHMM
Return duration in minutes: 15*60+36 - 14*60+02 => 94
Solution:
SELECT (CAST(SUBSTRING('1536',1,2) AS int)*60 + CAST(SUBSTRING('1536',3,2) AS int))
- (CAST(SUBSTRING('1402',1,2) AS int)*60 + CAST(SUBSTRING('1402',3,2) AS int));

Related

ORACLE-SQL : how to calculate 2 time in number type?

I kept my Time data as number type (NUMBER(4,2)) and I want to calculate the column like below
2.15 (2:15 am.) - 1.45 (1:45 am)
***result***
0.30 (a half hour)
Please kindly explain me the method to calculate.
Try this one I hove it will work for u
select to_char(to_date(((to_date(to_char(09.15),'hh24.mi')-to_date(to_char(01.45),'hh24.mi'))*24*60*60),'sssss'),'hh24:mi') time from dual;
Try this code:
select (trunc(2.15)* 0.6 + (2.15 - trunc(2.15))) - (trunc(1.45)* 0.6 + (1.45 - trunc(1.45)))
as result
from YOUR_TABLE
Result: 0,30
Assuming you can get them into separate columns:
with mins_calc as
(
select (floor(mytime1) - floor(mytime2))*60 + (mod(mytime1,1)-mod(mytime2,1)) as tot_mins
from Mytable
)
select to_char(floor(tot_mins/60))||'.'||to_char(mod(tot_mins,60)) as time_diff_char
from mins_calc
Convert to hours:
select ( trunc(t1) + (t1 - trunc(t1)) * 60) -
trunc(t2) + (t2 - trunc(t2)) * 60)
) as hours
This converts the difference to fractional hours. I would advise you to leave it like that or convert to minutes.
You can convert your two 'times' to minutes; this uses bind variables to provide both numeric values as it isn't clear where you're actually getting them from:
var time_1 number;
var time_2 number;
exec :time_1 := 2.15;
exec :time_2 := 1.45;
select 60 * trunc(:time_1) + 100 * (:time_1 - trunc(:time_1)) as minutes_1,
60 * trunc(:time_2) + 100 * (:time_2 - trunc(:time_2)) as minutes_2,
(60 * trunc(:time_1) + 100 * (:time_1 - trunc(:time_1)))
- (60 * trunc(:time_2) + 100 * (:time_2 - trunc(:time_2))) as minutes_diff
from dual;
MINUTES_1 MINUTES_2 MINUTES_DIFF
---------- ---------- ------------
135 105 30
You can then convert the difference in minutes back to a number in the (odd) format you're using by reversing the calculation; this uses a second CTE to get the difference in minutes calculated above to simplify things and avoid repeating the long terms:
with diff (minutes) as (
select (60 * trunc(:time_1) + 100 * (:time_1 - trunc(:time_1)))
- (60 * trunc(:time_2) + 100 * (:time_2 - trunc(:time_2)))
from dual
)
select minutes,
trunc(minutes/60) + mod(minutes, 60) / 100 as minutes_as_number
from diff;
MINUTES MINUTES_AS_NUMBER
---------- -----------------
30 .3
DATEDIFF (Transact-SQL)
This function returns the count (as a signed integer value) of the specified datepart boundaries crossed between the specified startdate and enddate.
//You can return: second, minute, day, year. In your case is minute.
SELECT DATEDIFF(minute, '2018-08-03 02:15:00am', '2018-08-03 1:45:00am');
return value: -30
if you would like to get exact (30) converted in varchar use like that.
SELECT CONVERT(varchar, ABS(DATEDIFF(minute, '2018-08-03 02:15:00am', '2018-08-03 1:45:00am')));
First use ABS() to get the absolute number (removing the (-) minus signal) and convert to varchar using CONVERT().
source: https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-2017
ORACLE Version
SELECT TO_DATE('2000-01-02', 'YYYY-MM-DD') - TO_DATE('2000-01-01', 'YYYY-MM-DD') AS DateDiff FROM dual

I am running this query in postgres saying error 'operator does not exist: interval + double precision'

I am using this query
SELECT
(date_trunc('hour', b.pub_ts) - DATE '1970-01-01')* 24 * 60 * 60 +
EXTRACT(SECOND FROM b.pub_ts),
date_trunc('hour', b.pub_ts)
from tablename b
limit 10;
ERROR: operator does not exist: interval + double precision
LINE 1: ...ur', b.pub_ts) - DATE '1970-01-01')* 24 * 60 * 60 + EXTRACT...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
After #Vao said i try the output is
the actual output should be
Because then i have to apply round on the decimal but it is coming in interval.
Like this
round (((date_trunc('hour', b.pub_ts) - DATE '1970-01-01')* 24 * 60 * 60) +
concat(EXTRACT(SECOND FROM b.pub_ts),' seconds')::interval,3)
instead of
+ EXTRACT(SECOND FROM b.pub_ts),
try
+concat(EXTRACT(SECOND FROM b.pub_ts),' seconds')::interval,
The idea behind is that seconds is the only part of interval (or timestamp) that can have decimals, so you need to explicitely define you add seconds with decimals - then it should accept it
The answer to question
> round((extract(epoch from ((date_trunc('hour', b.pub_ts) -
DATE '1970-01-01')* 24 * 60 * 60)) +
EXTRACT(SECOND FROM b.pub_ts))::numeric,3)
AND also if you want day to be extracted instead of eposh
(round((extract(DAY from((date_trunc('hour', b.pub_ts)
- DATE '1970-01-01')* 24 * 60 * 60)) +
EXTRACT(SECOND FROM b.pub_ts))::numeric,3) *1000 / 1000)
https://www.postgresql.org/message-id/3FCF7C40.2040505%40klaster.net

Show average difference between two time fields as MM:SS in SQL

I am using SQL Server 2008. I have several rows of start_time and end_time. I want to calculate the average difference between these two times in a MM:SS format.
start_time | end_time
10:15:30 | 10:15:45
10:45:00 | 10:47:30
Row 1 would be a difference of 00:15, and row 2 would be a difference of 02:30. The average of the entire dataset would be 01:23 (1 minute and 23 seconds).
The code I'm using looks like the following, but only returns an integer.
AVG(DATEDIFF(MI,start_time,end_time))
Thanks in advance for your help.
You're close, but you should use DateDiff() to get the average number of seconds between the two fields, rather than the average number of minutes.
With SQL Server 2008 R2, you don't have access to TIMEFROMPARTS() which would simplify the display greatly, so you'll have to convert this into a VARCHAR to get the format you want.
;With AverageSeconds As
(
Select Avg(DateDiff(Second, Start_Time, End_Time))) AvgSec
From YourTable
)
Select Right('00' + Convert(Varchar, (AvgSec / 60)), 2)
+ ':'
+ Right('00' + Convert(Varchar, (AvgSec % 60)), 2)
From AverageSeconds
You can convert the dates in unixtimestamp and then convert the seconds in a string.
Alternatively
right(convert(varchar(20), Dateadd(second, Avg(Datediff(second, Start_Time, End_Time)), 0), 120), 5)

Calculate the SUM of the Column which has Time DataType:

I want to calculate the Sum of the Field which has Time DataType.
My Table is Below:
TableA:
TotalTime
-------------
12:18:00
12:18:00
Here I want to sum the two time fields.
I tried the below Query
SELECT CAST(
DATEADD(MS, SUM(DATEDIFF(MS, '00:00:00.000',
CONVERT(TIME, TotalTime))), '00:00:00.000'
) AS TOTALTIME)
FROM [TableA]
But it gives the Output as
TOTALTIME
-----------------
00:36:00.0000000
But My Desired Output would be like below:
TOTALTIME
-----------------
24:36:00
How to get this Output?
You could sum the total number of seconds, or datediff(second,0,datecolumn). You can format that as a time string with some math. For example, the total number of minutes is totalseconds / 60 % 60. For example:
select cast(sum(datediff(second,0,dt))/3600 as varchar(12)) + ':' +
right('0' + cast(sum(datediff(second,0,dt))/60%60 as varchar(2)),2) +
':' + right('0' + cast(sum(datediff(second,0,dt))%60 as varchar(2)),2)
from TestTable
Working code at SQL Fiddle.
24:36 is the same as 00:36(Next day)
Your query is working fine the results are correct,
24:36 is the time 00:36 for next day.
You can display maximum 24 hrs. You are not using any day thats why every 24 hrs =0 hrs for next day.
Just change the column values and you can see that.
It would be a tad longwinded, but if you wanted to avoid the day rollover but you could split the second TIME into constituent datepart()'s and then add those on? (even display as a varchar if it's necessary to have an hour value greater than 24.
TRY THIS.
SELECT
CONVERT(VARCHAR(MAX),SUM(DATEPART(HH,CAST(YOUR_FIELD AS DATETIME)))+
(SUM(DATEPART(MINUTE,CAST(YOUR_FIELD AS DATETIME)))/60) +
(SUM(DATEPART(MINUTE,CAST(YOUR_FIELD AS DATETIME)))%60 +
(SUM(DATEPART(SECOND,CAST(YOUR_FIELD AS DATETIME)))/60))/60) + ':' +
RIGHT('00' + CONVERT(VARCHAR(MAX),
(SUM(DATEPART(MINUTE,CAST(YOUR_FIELD AS DATETIME)))%60+
(SUM(DATEPART(SECOND,CAST(YOUR_FIELD AS DATETIME)))/60))%60),2) + ':' +
RIGHT('00' + CONVERT(VARCHAR(MAX),SUM(DATEPART(SECOND,
CAST(YOUR_FIELD AS DATETIME)))%60),2) AS YOUR_FIELD
FROM YOUR_TABLE

Efficient way to convert second to minute and seconds in sql server 2005

Suppose I have 90 seconds. If I want to display the result in terms of minutes and second, I do it by using
select Time= '0' + CAST( 90/60 as varchar(2)) + ':' + CAST( 90%60 as varchar(2))
The output is
Time
01:30
I have appended 0(zero) because if you do a select getdate() the output will be
yyyy-mm-dd hh:mm:ss:ms
What is the standard way and recommended practice to do such a conversion?
Thanks
With hours:
SELECT CONVERT(CHAR(8),DATEADD(second,90,0),108)
00:01:30
Ignoring hours:
SELECT RIGHT(CONVERT(CHAR(8),DATEADD(second,90,0),108),5)
01:30
Try this:
select convert(varchar(10), dateadd(second, 15794, 0), 108)
One of the first things I do on a fresh SQL database is add a Timespan function similar to this one (although I tend to include days and milliseconds as well):
CREATE FUNCTION dbo.TimeSpan
(
#Hours int,
#Minutes int,
#Seconds int
)
RETURNS datetime
AS BEGIN
RETURN DATEADD(SS, #Hours * 3600 + #Minutes * 60 + #Seconds, 0)
END
Then you can format this however you want:
SELECT SUBSTRING(CONVERT(char(8), dbo.TimeSpan(0, 0, 90), 108), 4, 5)
It might look more complicated at first, but the ability to reuse the TimeSpan function comes in very handy over time. For me it feels like a hack to always be writing DATEADD calls against 0 or '1753-01-01'.