SQL query for finding difference of two time and sum - sql-server

I have this table in SQL Server:
UserId Date Start Time End Time
------------------------------------------------------------------------------------
20 2012-04-02 00:00:00.000 NULL 2012-04-02 09:17:57.000
20 2012-04-02 00:00:00.000 2012-04-02 09:17:57.000 2012-04-02 09:57:55.000
20 2012-04-02 00:00:00.000 2012-04-02 09:57:55.000 2012-04-02 10:04:58.000
20 2012-04-02 00:00:00.000 2012-04-02 10:04:58.000 2012-04-02 10:21:40.000
20 2012-04-02 00:00:00.000 2012-04-02 10:22:15.000 2012-04-02 10:22:20.000
20 2012-04-02 00:00:00.000 2012-04-02 10:22:56.000 2012-04-02 10:23:33.000
I want to find the difference between start time and end time and sum up the difference hours based on date
Output required is:
UserID Time_Duration
-----------------------
20 1:20:20 (this is example not actuals)
Can anyone help me write a SQL query..
I have tried with the below query,
select sum(sub1.TotalSeconds / 3600) as [Hours], sum((sub1.TotalSeconds % 3600) / 60)
as [Minutes],
sum((sub1.TotalSeconds % 3600) % 60) as [Seconds],sub1.Date
from
(
SELECT
sub.UserID,
sub.Date,
sum(datepart(hour, sub.end_time-sub.start_time) * 3600) + sum(datepart(minute, sub.end_time-sub.start_time) * 60) +
sum(datepart(second, sub.end_time-sub.start_time)) as TotalSeconds
from.......
) AS sub
group by sub.UserID,sub.Date,sub.start_time,sub.end_time)
as sub1 group by sub1.Date;
I get the following result
Hours Minutes Seconds Date
3 347 515 2012-04-02 00:00:00.000
But i want to add the minutes if greater then 60 it has to hours as 3+1 hr and so on. Can any 1 help me where Im making mistake

Hi take a look at this:
SQLFIDDLE
It is NOT the most efficient and I believe it's ugly for a code. However put it across for you to see the steps. You may get an idea out of it. Mainly using arimethic operators to get the reusults. There are extra fields as I was using it mainly to show you the data flow. I am sure other approaches are much much efficient in terms of performance. You can try.
Query:
select q.userid, t.date,
q.h + round((q.m + (q.s/60))/60,0) as hh,
round((q.m + (q.s/60)) mod 60,0) as mm,
q.s mod 60 as ss
from
(select t.userid,t.date,
sum(t.hours) as h,
sum(t.minutes) as m,
sum(t.seconds) as s
from (select userid,date,
TIMEDIFF(EndTime, StartTime) as duration,
TIMESTAMPDIFF(hour,starttime,endtime) as hours,
TIMESTAMPDIFF(minute,starttime,endtime) mod 60 as minutes,
TIMESTAMPDIFF(second,starttime,endtime) mod 60 seconds
from datestimes) as t
) as q
;
Resutls
USERID DATE HH MM SS
20 April, 02 2012 00:00:00+0000 13 4 25
Updated Query only with one nested query
Infact you may achieve this with one nested query. Apology as this whole answer is MYSQL based. So hopefully you may take the logic out to implement that using SQL Server syntax :)
select t.userid, t.date,
(sum(t.hours) + round((sum(t.minutes) +
sum(t.seconds)/60)/60,0)) as h,
(round((sum(t.minutes) +
sum(t.seconds)/60) mod 60,0)) as m,
sum(t.seconds) mod 60 as s
from
(select userid, date,
TIMEDIFF(EndTime, StartTime) as duration,
TIMESTAMPDIFF(hour,starttime,endtime) as hours,
TIMESTAMPDIFF(minute,starttime,endtime) mod 60 as minutes,
TIMESTAMPDIFF(second,starttime,endtime) mod 60 seconds
from datestimes) as t
;

You can do this matematically:
Select
CAST(DATEDIFF(SECOND, StartDate, EndDate) / 3600 as VARCHAR) + ':' +
CAST((DATEDIFF(SECOND, StartDate, EndDate) % 3600) / 60 as VARCHAR) + ':' +
CAST(DATEDIFF(SECOND, StartDate, EndDate) % 60 as VARCHAR) as DateDifference
From YourTable
DATEDIFF function gives you difference in seconds between start and end time as integer value. Simple dividing that value with 3600, or 60, you've got hours, or minutes, and with % you've got remain values.

Declare #test table(start datetime,ende datetime)
insert into #test Values ('20120101 10:00','20120101 18:00')
insert into #test Values ('20120101 10:00','20120101 18:13')
insert into #test Values ('20120101 10:00','20120102 18:25')
insert into #test Values ('20120101 10:00','20120101 18:00')
insert into #test Values ('20120101 10:00','20120101 18:00')
Select
FLOOR(Cast(Dummy as Float)) as Days
,DATEPART(Hour,dummy) as Hours
,DATEPART(MINUTE,dummy) as Minutes
,DATEPART(Second,dummy) as Seconds
from
(
Select
DateAdd(second, SUM(DATEDIFF(SECOND,start,ende)),Cast(0 as Datetime)) as Dummy
from #test
) a

Related

Calculating Early and Late Dates for Performance Measurement

I am trying to calculate shipping performance in SSMS- Im getting stuck in several areas and I hope i can get some help!
I have an Estimated Ship Date, an Appt Date, and an Actual Ship date.
Im measuring warehouse performance, so in most cases shipments leave same day. But in others, they may leave a few days early or late.
The problem that i am having is the correct output. I want to show the Values in DD:HH:MM, but the syntax for DateDiff doesn't give me an accurate day to use:
For Example, a shipment was supposed to leave on 6/3/2019 # at 8 am, but didnt leave the warehouse until 7/22/2019 # 6:30 AM. In this case, DateDiff calcs 49 days, when really its 48 days 22 hours and 30 minutes late. Here is an example of some of the syntax i am using:
EstimatedShipDate datetime,
AppointmentShipDate datetime,
ActualShipDate datetime
);
insert into #test values ('2019-07-01 11:00', '2019-07-01 11:00','2019-06-30 10:30');
insert into #test values ('2019-07-08 13:45', null,'2019-07-01 22:00');
insert into #test values ('2019-07-09 15:00', null,'2019-07-10 15:00');
insert into #test values ('2019-07-03 15:00', null,'2019-07-04 15:00');
insert into #test values ('2019-07-08 15:00', null,'2019-07-08 15:00');
insert into #test values ('2019-07-08 15:00', null,'2019-07-08 22:00');
insert into #test values ('2019-07-03 08:00', null,'2019-07-04 15:00');
insert into #test values ('2019-07-03 08:00', null,'2019-07-03 06:30');
insert into #test values ('2019-06-03 08:00', null,'2019-07-22 06:30');
insert into #test values ('2019-07-01 11:00', null,'2019-06-29 10:30');
Select
EstimatedShipDate,
AppointmentShipDate,
ActualShipDate,
DATEDIFF(DAY,ISNULL(CAST(AppointmentShipDate as DateTime),CAST(EstimatedShipDate as DateTime)), CAST(ActualShipDate as DateTime)) as Days,
DATEPART(DAY, ISNULL(CAST(AppointmentShipDate as DateTime),CAST(EstimatedShipDate as DateTime))-CAST(ActualShipDate as DateTime) ) as days2,
DATEDIFF(Hour,ISNULL(CAST(AppointmentShipDate as DateTime),CAST(EstimatedShipDate as DateTime)), CAST(ActualShipDate as DateTime)) as Hours,
convert(varchar, CAST(ActualShipDate as DateTime)-ISNULL(CAST(AppointmentShipDate as DateTime),CAST(EstimatedShipDate as DateTime)),108) as DateSubtract_Convert,
convert(varchar,ISNULL(CAST(AppointmentShipDate as DateTime),CAST(EstimatedShipDate as DateTime)-CAST(ActualShipDate as DateTime) ),108) as DateSubtract_ConvertEarly
from #TEST
In this case, DateDiff calcs 49 days, when really its 48 days 22 hours and 30 minutes late. Or vice versa, I have a date range that shows 2 days 23:20 but it should be 1 day 23:20
One way is to increase granularity of DATEDIFF to MINUTE. That will require calculation for the days, hours, and minutes using the minutes (division and mod).
SELECT ABS(dT.diff_Minutes / 1440) AS [Days] --days, there are 1440 minutes in a day
,ABS((dT.diff_Minutes % 1440) / 60) AS [Hours] --hours remaining in the day
,ABS((dT.diff_Minutes % 1440) % 60) AS [Minutes] --minutes remaining in the day
FROM (
SELECT DATEDIFF(MINUTE, ISNULL(AppointmentShipDate, EstimatedShipDate), ActualShipDate) [diff_Minutes]
FROM #test
) AS dT
Your temp table produces output:
Days Hours Minutes
1 0 30
6 15 45
1 0 0
1 0 0
0 0 0
0 7 0
1 7 0
0 1 30
48 22 30
2 0 30
To put these in DD:HH:MM format is more complicated, but you can cast the numbers to varchar and concatenate as strings. RIGHT is used to add any leading zeroes.
SELECT CASE WHEN dT.diff_Minutes < 0 THEN '- ' ELSE '+ ' END --positive or negative
+ RIGHT('00' + CAST(ABS(dT.diff_Minutes / 1440) as varchar(1000)), 2)
+ ':'
+RIGHT('00' + CAST((ABS(dT.diff_Minutes % 1440) / 60) as varchar(2)), 2)
+ ':'
+RIGHT('00' + CAST((ABS(dT.diff_Minutes % 1440) % 60) as varchar(2)), 2)
AS [DD:HH:MM]
FROM (
SELECT DATEDIFF(MINUTE, ISNULL(AppointmentShipDate, EstimatedShipDate), ActualShipDate) [diff_Minutes]
FROM #test
) AS dT
Produces output:
DD:HH:MM
- 01:00:30
- 06:15:45
+ 01:00:00
+ 01:00:00
+ 00:00:00
+ 00:07:00
+ 01:07:00
- 00:01:30
+ 48:22:30
- 02:00:30
Use seconds instead of days and then do a little math with seconds, minutes and hours.
Here's a simple SSMS example:
DECLARE
#ScheduledDate DATETIME = '6/3/2019 08:00:00',
#ShippedDate DATETIME = '07/22/2019 06:30:00';
SELECT
CONVERT( VARCHAR, DATEDIFF( s, #ScheduledDate, #ShippedDate ) /60/60/24 ) + ' Days and '
+ CONVERT( VARCHAR, ( #ShippedDate - #ScheduledDate ), 108 ) + ' Hours.';
Returns
48 Days and 22:30:00 Hours.

Convert number of minutes to hh:mm

I have a column in a table that stores the number of minutes as a numeric(18,4) field named [course_access_minutes].
The stored values come from a blackboard database and look like this:
0.0500
0.0667
0.3667
up to
314.0833
625.8167
How do I convert these to time hh:mm, I've had a good look at the database documentation and all I can find is
course_access_minutes numeric(18,4) This is the number of minutes that the user accesses this course in total during this login session.
Can I assume that I can make a direct conversion from minutes into hours? I think I will take any values below 1 as 0 minutes. What is the best way to do this in SQL? Thanks in advance for your help.
Try this
SELECT CONVERT(varchar, DATEADD(s, 625.8167 * 60, 0), 108)
If the duration is longer than 24 hours you can use this
SELECT CONVERT(varchar, CAST(1877.4501 * 60 AS int) / 3600)
+ RIGHT(CONVERT(varchar, DATEADD(s, 1877.4501 * 60, 0), 108), 6)
You could use FLOOR like this
DECLARE #SampleData AS TABLE
(
Minutes numeric(18,4)
)
INSERT INTO #SampleData
VALUES
( 0.0500),
( 1.0500),
( 30.0500),
( 80.0500),
( 314.0833),
( 625.8167)
SELECT CONCAT(floor(sd.Minutes/60),':', CASE WHEN sd.Minutes - floor(sd.Minutes/60)*60 < 1 THEN '0'
ELSE FLOOR(sd.Minutes - floor(sd.Minutes/60)*60 )
END) AS hours
FROM #SampleData sd
Returns
hours
0:0
0:1
0:30
1:20
5:14
10:25
WITH _Samples AS (
SELECT CONVERT(numeric(18, 4), 0.0500) [course_access_minutes]
UNION ALL SELECT 0.0667
UNION ALL SELECT 0.3667
UNION ALL SELECT 314.0833
UNION ALL SELECT 625.8167
)
SELECT
S.course_access_minutes,
-- split out the number
FLOOR(S.course_access_minutes / 60) [hours],
FLOOR(S.course_access_minutes % 60) [minutes],
FLOOR((S.course_access_minutes - FLOOR(S.course_access_minutes)) * 60) [seconds],
-- to a string
CONVERT(varchar(10), FLOOR(S.course_access_minutes / 60))
+ ':' + RIGHT('00' + CONVERT(varchar(10), FLOOR(S.course_access_minutes % 60)), 2)
+ ':' + RIGHT('00' + CONVERT(varchar(10), FLOOR((S.course_access_minutes - FLOOR(S.course_access_minutes)) * 60)), 2) [time_string],
-- You could consider converting to the time data type if the values will never exceed the limit
-- time supports 00:00:00.0000000 through 23:59:59.9999999
-- 0 through 1439.9833333 ... 23 * 60 = 1380 + 59 = 1439 + (59 / 60) = 1439.9833333
-- (see: https://learn.microsoft.com/en-us/sql/t-sql/data-types/time-transact-sql)
CONVERT(time,
CONVERT(varchar(10), FLOOR(S.course_access_minutes / 60))
+ ':' + RIGHT('00' + CONVERT(varchar(10), FLOOR(S.course_access_minutes % 60)), 2)
+ ':' + RIGHT('00' + CONVERT(varchar(10), FLOOR((S.course_access_minutes - FLOOR(S.course_access_minutes)) * 60)), 2)
) [time]
FROM
_Samples S
(It wouldn't be difficult to further this idea and split out the fractional seconds as well.)
Which yields:
course_access_minutes hours minutes seconds time_string time
---------------------- ------ -------- -------- ------------ ----------------
0.0500 0 0 3 0:00:03 00:00:03.0000000
0.0667 0 0 4 0:00:04 00:00:04.0000000
0.3667 0 0 22 0:00:22 00:00:22.0000000
314.0833 5 14 4 5:14:04 05:14:04.0000000
625.8167 10 25 49 10:25:49 10:25:49.0000000
Note that this is going to be like Greg's answer, but I wanted to explain and simplify it.
You have minutes, so dividing them by 60 and flooring it (removing the decimal) gives the hours (without the minutes).
If you take the total minutes again, and remove (mod it by) the floored hours - which requires conversion to minutes by multiplying by 60 - you are left with the remaining minutes by essentially just finding out what is left after taking away that many groups of sixties:
SELECT FLOOR(course_access_minutes / 60) as Hours,
(FLOOR(course_access_minutes) % 60) as Minutes
FROM MyTable
If you want the decimal to appear for the amount of minute fractions (you want the seconds to appear, in decimal form), remove FLOOR.
If you want seconds in real numbers, keep FLOOR and use what Greg had: FLOOR((S.course_access_minutes - FLOOR(S.course_access_minutes)) * 60) for seconds. Be careful with the parenthesis, though, because you can end up accidentally flooring your decimaled minutes and get 0, and then 0*60 is zero:
FLOOR(
(
course_access_minutes -
FLOOR(course_access_minutes)
) * 60
) as Seconds

Select part of duration that occurs in specific hour of day

In SQL Server, I have a table of processes with a starttime and an endtime, from which I can calculate a duration using DATEDIFF.
Name StartTime EndTime
------------------------------------------------
process1 2016-10-10 11:10 2016-10-10 11:20
process2 2016-10-10 11:40 2016-10-10 12:30
How can I select the timespan of the process duration that occured in specific hours of the day (11 and 12) in seconds?
So process1 would be 10 minutes in hour 11.
process2 would be 20 minutes in hour 11, 30 minutes in hour 12.
Here's a sample that will generate hourly records for each source record. It uses a recursive CTE to move from the StartTime of each record through the EndTime. It may need some slight modifications to make it work in your case, but hopefully you can get the idea of how this method works.
Note that, as shown in the sample below, this will work properly even if the time span crosses a date boundary.
--==================================================================================
-- Do some quick setup to get a temporary table populated with data to use:
--==================================================================================
IF OBJECT_ID('tempdb..#ProcessHistory', 'U') IS NOT NULL DROP TABLE #ProcessHistory;
CREATE TABLE #ProcessHistory (
Name VARCHAR(20),
StartTime DATETIME,
EndTime DATETIME
)
INSERT INTO #ProcessHistory
VALUES ('process1', '2016-10-10 11:10', '2016-10-10 11:20'),
('process2', '2016-10-10 11:40', '2016-10-10 12:30'),
('process3', '2016-10-10 22:21', '2016-10-11 02:36');
--==================================================================================
-- Use a recursive CTE to generate hourly data for each record:
--==================================================================================
WITH HourlyData AS (
-- Anchor:
SELECT
ph.Name [ProcessName],
ph.StartTime [StartTime],
ph.EndTime [EndTime],
-- Get the current hour with date:
DATEADD(MINUTE, -DATEPART(MINUTE, ph.StartTime), ph.StartTime) [CurrentHour],
-- Calculate the next hour for use later:
DATEADD(MINUTE, 60 - DATEPART(MINUTE, ph.StartTime), ph.StartTime) [NextHour],
-- Determine how many minutes the process was active this hour:
CASE
WHEN DATEDIFF(MINUTE, ph.StartTime, ph.EndTime) > 60 - DATEPART(MINUTE, ph.StartTime)
THEN 60 - DATEPART(MINUTE, ph.StartTime)
ELSE DATEDIFF(MINUTE, ph.StartTime, ph.EndTime)
END [Minutes]
FROM #ProcessHistory ph
UNION ALL
-- Recurse:
SELECT
hd.ProcessName,
hd.StartTime,
hd.EndTime,
hd.NextHour [CurrentHour],
DATEADD(HOUR, 1, hd.NextHour) [NextHour],
-- Determine how many minutes the process was active this hour:
CASE
WHEN DATEDIFF(MINUTE, hd.NextHour, hd.EndTime) < 60
THEN DATEDIFF(MINUTE, hd.NextHour, hd.EndTime)
ELSE 60
END
FROM HourlyData hd
WHERE hd.NextHour < hd.EndTime
)
SELECT
hd.ProcessName,
hd.CurrentHour [HourWithDate],
CONVERT(DATE, hd.CurrentHour) [Date],
DATEPART(HOUR, hd.CurrentHour) [Hour],
hd.Minutes
FROM HourlyData hd
ORDER BY
hd.ProcessName,
hd.CurrentHour;
The output from the above sample would look like this:
ProcessName HourWithDate Date Hour Minutes
process1 2016-10-10 11:00:00.000 2016-10-10 11 10
process2 2016-10-10 11:00:00.000 2016-10-10 11 20
process2 2016-10-10 12:00:00.000 2016-10-10 12 30
process3 2016-10-10 22:00:00.000 2016-10-10 22 39
process3 2016-10-10 23:00:00.000 2016-10-10 23 60
process3 2016-10-11 00:00:00.000 2016-10-11 0 60
process3 2016-10-11 01:00:00.000 2016-10-11 1 60
process3 2016-10-11 02:00:00.000 2016-10-11 2 36
To handle general cases, you could try something like
--drop table #processes
CREATE TABLE #processes
(
name varchar(50),
StartTime Datetime,
EndTime DateTime
);
insert #processes VALUES('proc1','20161010 11:10','20161010 11:20');
insert #processes VALUES('proc2','20161010 11:40','20161010 12:20');
insert #processes VALUES('proc3','20161010 10:40','20161010 12:20');
;WITH HRS AS (SELECT 0 HR
UNION ALL
SELECT HR + 1 FROM HRS WHERE HR < 23),
MINS AS (SELECT 0 MN
UNION ALL
SELECT MN + 1 FROM MINS WHERE MN < 59),
TIMES AS (SELECT HR,MN FROM HRS CROSS JOIN MINS)
SELECT name,starttime,endtime,Count(0) AS mins FROM #processes
JOIN TIMES
ON (HR > datepart(hh,Starttime)
OR HR = datepart(hh,Starttime) AND MN >= datepart(n,STARTtIME))
AND
(HR < datepart(hh, EndTime)
OR HR = datepart(hh, EndTime) AND MN < datepart(n,EndTime))
WHERE HR = 11 --hour is 11
GROUP BY name,
starttime,
endtime
drop table #processes;
create table #temp (Name varchar(5), starttime datetime, EndTime datetime)
insert into #temp values(1,'2016-10-10 11:10','2016-10-10 11:20' )
insert into #temp values(2,'2016-10-10 11:40','2016-10-10 12:30' )
insert into #temp values(2,'2016-10-10 10:40','2016-10-10 11:30' )
insert into #temp values(2,'2016-10-10 10:40','2016-10-10 12:30' )
DECLARE #firstTime time ,#secondTime time
set #firstTime ='11:00'
set #secondTime ='12:00'
select
CASE WHEN CONVERT(time(0), starttime) < #firstTime AND CONVERT(time(0), EndTime) > #secondTime THEN DATEDIFF(ss,#firstTime,#secondTime)
WHEN CONVERT(time(0), EndTime) > #secondTime THEN DATEDIFF(ss,CONVERT(time(0), starttime),#secondTime)
WHEN CONVERT(time(0), starttime) < #firstTime THEN DATEDIFF(ss,CONVERT(time(0), EndTime),#secondTime)
ELSE DATEDIFF(ss,starttime,EndTime)
END
from #temp
SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,'2016-10-10 11:10','2016-10-10 12:20'),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference
With timeDifference -
SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,StartTime,EndTime),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference
from #YourTableName
With Days and TimeDiffernece
declare #start_time as varchar(150);
declare #end_time as varchar(150);
set #start_time='2016-10-10 10:10';
set #end_time='2016-10-12 12:10'
SELECT datediff(day,#start_time,#end_time) as dayDifference,
CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,#start_time,#end_time),'2011-01-01 00:00:00') AS TIME(0))
as timeDifference
I think this does the trick, but it's pretty ugly. Maybe someone can do it more elegantly?
SELECT
case
when HOUR(starttime) < 11 AND HOUR(endtime) = 11 then minute(endtime)
when HOUR(starttime) < 11 AND HOUR(endtime) > 11 then 60
when HOUR(starttime) = 11 AND HOUR(endtime) = 11 then minute(endtime) - minute(starttime)
when HOUR(starttime) = 11 AND HOUR(endtime) > 11 then 60 - minute(starttime)
else 0
end AS ProcessTimeHour_11,
case
when HOUR(starttime) < 12 AND HOUR(endtime) = 12 then minute(endtime)
when HOUR(starttime) < 12 AND HOUR(endtime) > 12 then 60
when HOUR(starttime) = 12 AND HOUR(endtime) = 12 then minute(endtime) - minute(starttime)
when HOUR(starttime) = 12 AND HOUR(endtime) > 12 then 60 - minute(starttime)
else 0
end AS ProcessTimeHour_12
from StuffAndThings

date & time difference format

I have a Login/Logout system that compute the total hours work of the employees. My problem is the formatting of the date&time difference for minutes.
Example:
if user logged-in 8:00 AM and logged-out 6:30 PM, the total should be 10.50 but my SQL output is 10 hrs and 30 mins. I know the formula(it should be 30mins/60 = 50) but I didn't know where should I put that Dividend(/60) on my SQL Query.(see below my SQL Code).
SQL Code:
SELECT *,CAST(Datediff(HOUR, 0, logout_time - login_time) +
Cast(Datediff(MINUTE, 0, logout_time - login_time) -
(Datediff(HOUR, 0, logout_time - login_time) * 60 ) AS DECIMAL) / 100 AS Decimal(18,2)) AS [TotalHrs_Worked]
FROM table_DTR
WHERE CONVERT(VARCHAR(10),log_date, 101) BETWEEN '09/01/2014' AND '11/30/2014'
If you simply take the minutes between a pair of datetime values and multiply it by 60.0 (with a decimal place so it produces a result with a decimal value), this should work without problem:
Run this example:
DECLARE #start DATETIME = '2014-12-15 08:00:00'
DECLARE #end DATETIME = '2014-12-15 18:30:00'
SELECT DATEDIFF(minute, #start, #end)/60.0 AS HoursWorked
This will produce:
10.50
You shouldn't need to break it down in to minutes and hours like you are doing in your SQL.

Calculate date between two date and sum then convert into hours and minutes

I want to get the Date difference in hours and minutes and to achieve that I have used this query in SQL Server:
Cast(SUM(DATEDIFF(second, fromtime, totime) / 60 / 60 % 24) as varchar(20)) + ' hours '
+CAST(SUM(DATEDIFF(second, fromtime, totime) / 60 % 60)as varchar(20))+' minutes ' as [TotalTime]
It returns the following Output:
TotalTime
---------------------
16 Hours 120 Minutes
3 Hours 90 Minutes
but the expected output is:
TotalTime
----------------------
18 Hours 0 Minutes
4 Hours 30 Minutes.
Can anyone help me to solve this issue?
Your query is perfect, All you need to do is to write a outer query over it. Something like below
select case when t.minutes>60 then t.hours+(t.minutes/60) else t.hours end as hours,
case when t.minutes>60 then t.minutes%60 else t.minutes end as minutes
from
(
select
Cast(SUM(DATEDIFF(second, fromtime, totime) / 60 / 60 % 24) as varchar(20)) as hours
+CAST(SUM(DATEDIFF(second, fromtime, totime) / 60 % 60)as varchar(20)) as minutes
from tablename
)as t

Resources