How to SUM hours, minutes and seconds? - sql

I need to sum hours, minutes and seconds, using Sql Server 2008
The Field contains time values only.
Input
ID HORA_S
-- ----------------------
1 1899-12-30 18:22:50.000
2 1899-12-30 18:22:50.000
3 1899-12-30 18:30:50.000
Output
HOURS MINUTES SECONDS
---- --- --------
55 16 30
After playing arround with this code I resolved !!!
SELECT SUM(DATEPART(hh, CAST(HORA_S AS DATETIME)))
+ ( SUM(DATEPART(MINUTE, CAST(HORA_S AS DATETIME))) / 60 )
+ ( SUM(DATEPART(MINUTE, CAST(HORA_S AS DATETIME))) % 60
+ ( SUM(DATEPART(SECOND, CAST(HORA_S AS DATETIME))) / 60 ) ) / 60 AS HORAS,
( SUM(DATEPART(MINUTE, CAST(HORA_S AS DATETIME))) % 60
+ ( SUM(DATEPART(SECOND, CAST(HORA_S AS DATETIME))) / 60 ) ) % 60 AS MINUTOS,
SUM(DATEPART(SECOND, CAST(HORA_S AS DATETIME))) % 60 AS SEGUNDOS FROM Table

Here's a working example with a little less code
Sample table
DECLARE #T TABLE (ID int, HORA_S datetime)
insert #T values
(1, '1899-12-30 18:22:50.000'),
(2, '1899-12-30 18:22:50.000'),
(3, '1899-12-30 18:30:50.000')
;WITH T(V) AS (
SELECT convert(datetime,SUM(convert(float, 2+hora_s)))
FROM #T
)
SELECT
[HOURS] = floor(convert(float,V)*24),
[MINUTES] = DATEPART(MI,V),
[SECONDS] = DATEPART(SS,V)
FROM T
Note: The 2+ in the query assumes that by storing time only, the date portion will always be 1899-12-30. I know that Delphi uses that date as day 0.

Related

How to calculate the sum of time with SQL SERVER? [duplicate]

I have a column called "WrkHrs" and the data type is time(hh:mm:ss). I want to sum up the working hours for employees. But since it's time data type sql server doesn't let me use like sum(columnname).
How can I sum up the time data type fieled in sql query?
SELECT EmployeeID, minutes_worked = SUM(DATEDIFF(MINUTE, '0:00:00', WrkHrs))
FROM dbo.table
-- WHERE ...
GROUP BY EmployeeID;
You can format it pretty on the front end. Or in T-SQL:
;WITH w(e, mw) AS
(
SELECT EmployeeID, SUM(DATEDIFF(MINUTE, '0:00:00', WrkHrs))
FROM dbo.table
-- WHERE ...
GROUP BY EmployeeID
)
SELECT EmployeeID = e,
WrkHrs = RTRIM(mw/60) + ':' + RIGHT('0' + RTRIM(mw%60),2)
FROM w;
However, you're using the wrong data type. TIME is used to indicate a point in time, not an interval or duration. Wouldn't it make sense to store their work hours in two distinct columns, StartTime and EndTime?
In order to sum up the working hours for an employee you can calculate the difference between the shift start time and end time in minutes and convert it to readable format as following:
DECLARE #StartTime datetime = '08:00'
DECLARE #EndTime datetime = '10:47'
DECLARE #durMinutes int
DECLARE #duration nvarchar(5)
SET #durMinutes = DATEDIFF(MINUTE, #StartTime, #EndTime)
SET #duration =
(SELECT RIGHT('00' + CAST((#durMinutes / 60) AS VARCHAR(2)),2) + ':' +
RIGHT('00' + CAST((#durMinutes % 60) AS VARCHAR(2)), 2))
SELECT #duration
The result : 02:47
two hours and 47 minutes
select DATEDIFF(MINUTE, '0:00:00', '00:02:08')
results in :- 2
select DATEDIFF(SECOND, '0:00:00', '00:02:08')
results in :- 128
Using seconds gives a better answer.
So I think the answer can be
SELECT
EmployeeId
, seconds_worked = SUM (DATEDIFF (SECOND, '0:00:00', WrkHrs))
FROM
tbl_employee
GROUP BY
EmployeeId;
DECLARE #Tab TABLE
(
data CHAR(5)
)
INSERT #Tab
SELECT '25:30' UNION ALL
SELECT '31:45' UNION ALL
SELECT '16:00'
SELECT STUFF(CONVERT(CHAR(8), DATEADD(SECOND, theHours + theMinutes,
'19000101'), 8), 1, 2, CAST((theHours + theMinutes) / 3600 AS VARCHAR(12)))
FROM (
SELECT ABS(SUM(CASE CHARINDEX(':', data) WHEN 0 THEN 0 ELSE 3600 *
LEFT(data, CHARINDEX(':', data) - 1) END)) AS theHours,
ABS(SUM(CASE CHARINDEX(':', data) WHEN 0 THEN 0 ELSE 60 *
SUBSTRING(data, CHARINDEX(':', data) + 1, 2) END)) AS theMinutes
FROM #Tab
) AS d
For MS SQL Server, when your WorkingTime is stored as a time, or a varchar in order to sum it up you should consider that:
1) Time format is not supporting sum, so you need to parse it
2) 23:59:59.9999999 is the maximum value for the time.
So, the code that will work to get you the total number of WorkingHours:WorkingMinutes:WorkingSeconds would be the following:
SELECT
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) / 3600),'00') as varchar(max)) + ':' +
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) % 3600 / 60),'00') as varchar(max)) + ':' +
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) % 3600 % 60),'00') as varchar(max)) as WorkingTimeSum
FROM TableName
It must be as simple as that.
Steps
convert time to seconds
sum the RESULT
convert the sum to time
Eg:
take a case you might want to sum the following time:
| present_hours |
|-----------------|
| 00:01:20.000000 |
|-----------------|
| 00:01:13.000000 |
|-----------------|
| 00:01:45.000000 |
|-----------------|
| 00:01:03.000000 |
|-----------------|
| 00:01:10.000000 |
|-----------------|
| 00:00:56.000000 |
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(present_hours))) as total_present_hours FROM time_booking;

Extracting Day/Hour/Minute

I have the following code which is working, however how do I get the terminal minutes to show the output as Day, Hour, Minute? If this cannot be done, is it possible to add a +1 on the time which would indicate it's the following day?
The problem I am having is that when our orders run past 23.59 PM, the system is not displaying the correct format because of the 24 hour time period.
I am stumped and hope I am not confusing matters.
SELECT FOLIO_NUMBER, TERMINAL_NAME,
format((START_LOAD_TIME - ORDER_ENTRY_TIME), 'HH:mm') AS STAGING_MINUTES,
format((TERM_END_LOAD_TIME - START_LOAD_TIME), 'HH:mm') AS LOADING_MINUTES,
format((TERM_END_LOAD_TIME - ORDER_ENTRY_TIME), 'HH:mm') AS TERMINAL_MINUTES
FROM ORDERS
JOIN TERMINAL_OWNER ON ORDERS.LOADING_TERMINAL_ID = TERMINAL_OWNER.TERMINAL_ID
DECLARE #INT INT
SET #INT = DATEDIFF(SECOND,GETDATE(),GETDATE()+1)
select
convert(varchar(10), (#INT/86400)) + ':' +
convert(varchar(10), ((#INT%86400)/3600)) + ':'+
convert(varchar(10), (((#INT%86400)%3600)/60)) + ':'+
convert(varchar(10), (((#INT%86400)%3600)%60)) as 'DD:HH:MM:SS'
Courtesy of Nat-MS. See here
I think you are looking for something like this
Declare #theMinutes Varchar(10)
Set #theMinutes = '19:25'
declare #totMintute int
Select
#totMintute = (Cast(
Cast(left(#theMinutes,charindex(':',#theMinutes)-1) as Int) * 60
+ Cast(substring(#theMinutes,charindex(',',#theMinutes)+4,len(#theMinutes)) as Int)
as Int ) * 60) / 60
--For 12 hour 1 days
Select #totMintute / 720 as NoDays -- 720 minutes per day
, (#totMintute % 720) / 60 as NoHours -- modulo 720
, (#totMintute % 60) as NoMinutes -- modulo 60
--For 24 hour 1 days
Select #totMintute / 1440 as NoDays -- 1440 minutes per day
, (#totMintute % 1440) / 60 as NoHours -- modulo 1440
, (#totMintute % 60) as NoMinutes -- modulo 60
The output will look like as shown below.
You can convert this query data source table as shown below.
Create table #Temp (MinValue Varchar(8))
insert into #Temp Values ('19:25')
Select TotMinute / 720 as NoDays -- 1440 minutes per day
, (TotMinute % 720) / 60 as NoHours -- modulo 1440
, (TotMinute % 60) as NoMinutes -- modulo 60
from(
select
(Cast(
Cast(left(MinValue,charindex(':',MinValue)-1) as Int) * 60
+ Cast(substring(MinValue,charindex(',',MinValue)+4,len(MinValue)) as Int)
as Int ) * 60) / 60 as TotMinute
from #Temp
)a
You can find the live demo here.
I would say that you should remove the need to identify days/hours in the SQL Output and just get the difference in minutes, which you can then work with in your application layer.
Take this sample code:
create table #orders (
FOLIO_NUMBER int,
START_LOAD_TIME datetime,
ORDER_ENTRY_TIME datetime,
TERM_END_LOAD_TIME datetime
)
insert into #orders (FOLIO_NUMBER,START_LOAD_TIME,ORDER_ENTRY_TIME,TERM_END_LOAD_TIME)
values (1, getdate(),getdate() - 1,getdate() + 1)
select *,
datediff(mi, ORDER_ENTRY_TIME, START_LOAD_TIME) AS STAGING_MINUTES,
datediff(mi, START_LOAD_TIME, TERM_END_LOAD_TIME) AS LOADING_MINUTES,
datediff(mi, ORDER_ENTRY_TIME, TERM_END_LOAD_TIME) AS TERMINAL_MINUTES
from #orders
drop table #orders
This will output the minutes difference between the events:
FOLIO_NUMBER STAGING_MINUTES LOADING_MINUTES TERMINAL_MINUTES
1 1440 1440 2880
You can then perform some simple maths with these values to extract, days, hours and minutes.

How to sum up time field in SQL Server

I have a column called "WrkHrs" and the data type is time(hh:mm:ss). I want to sum up the working hours for employees. But since it's time data type sql server doesn't let me use like sum(columnname).
How can I sum up the time data type fieled in sql query?
SELECT EmployeeID, minutes_worked = SUM(DATEDIFF(MINUTE, '0:00:00', WrkHrs))
FROM dbo.table
-- WHERE ...
GROUP BY EmployeeID;
You can format it pretty on the front end. Or in T-SQL:
;WITH w(e, mw) AS
(
SELECT EmployeeID, SUM(DATEDIFF(MINUTE, '0:00:00', WrkHrs))
FROM dbo.table
-- WHERE ...
GROUP BY EmployeeID
)
SELECT EmployeeID = e,
WrkHrs = RTRIM(mw/60) + ':' + RIGHT('0' + RTRIM(mw%60),2)
FROM w;
However, you're using the wrong data type. TIME is used to indicate a point in time, not an interval or duration. Wouldn't it make sense to store their work hours in two distinct columns, StartTime and EndTime?
In order to sum up the working hours for an employee you can calculate the difference between the shift start time and end time in minutes and convert it to readable format as following:
DECLARE #StartTime datetime = '08:00'
DECLARE #EndTime datetime = '10:47'
DECLARE #durMinutes int
DECLARE #duration nvarchar(5)
SET #durMinutes = DATEDIFF(MINUTE, #StartTime, #EndTime)
SET #duration =
(SELECT RIGHT('00' + CAST((#durMinutes / 60) AS VARCHAR(2)),2) + ':' +
RIGHT('00' + CAST((#durMinutes % 60) AS VARCHAR(2)), 2))
SELECT #duration
The result : 02:47
two hours and 47 minutes
select DATEDIFF(MINUTE, '0:00:00', '00:02:08')
results in :- 2
select DATEDIFF(SECOND, '0:00:00', '00:02:08')
results in :- 128
Using seconds gives a better answer.
So I think the answer can be
SELECT
EmployeeId
, seconds_worked = SUM (DATEDIFF (SECOND, '0:00:00', WrkHrs))
FROM
tbl_employee
GROUP BY
EmployeeId;
DECLARE #Tab TABLE
(
data CHAR(5)
)
INSERT #Tab
SELECT '25:30' UNION ALL
SELECT '31:45' UNION ALL
SELECT '16:00'
SELECT STUFF(CONVERT(CHAR(8), DATEADD(SECOND, theHours + theMinutes,
'19000101'), 8), 1, 2, CAST((theHours + theMinutes) / 3600 AS VARCHAR(12)))
FROM (
SELECT ABS(SUM(CASE CHARINDEX(':', data) WHEN 0 THEN 0 ELSE 3600 *
LEFT(data, CHARINDEX(':', data) - 1) END)) AS theHours,
ABS(SUM(CASE CHARINDEX(':', data) WHEN 0 THEN 0 ELSE 60 *
SUBSTRING(data, CHARINDEX(':', data) + 1, 2) END)) AS theMinutes
FROM #Tab
) AS d
For MS SQL Server, when your WorkingTime is stored as a time, or a varchar in order to sum it up you should consider that:
1) Time format is not supporting sum, so you need to parse it
2) 23:59:59.9999999 is the maximum value for the time.
So, the code that will work to get you the total number of WorkingHours:WorkingMinutes:WorkingSeconds would be the following:
SELECT
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) / 3600),'00') as varchar(max)) + ':' +
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) % 3600 / 60),'00') as varchar(max)) + ':' +
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) % 3600 % 60),'00') as varchar(max)) as WorkingTimeSum
FROM TableName
It must be as simple as that.
Steps
convert time to seconds
sum the RESULT
convert the sum to time
Eg:
take a case you might want to sum the following time:
| present_hours |
|-----------------|
| 00:01:20.000000 |
|-----------------|
| 00:01:13.000000 |
|-----------------|
| 00:01:45.000000 |
|-----------------|
| 00:01:03.000000 |
|-----------------|
| 00:01:10.000000 |
|-----------------|
| 00:00:56.000000 |
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(present_hours))) as total_present_hours FROM time_booking;

SQL Server: hour and minute average

In SQL Server, I have a start time column on a table such as:
2011-09-18 08:06:36.000
2011-09-19 05:42:16.000
2011-09-20 08:02:26.000
2011-09-21 08:37:24.000
2011-09-22 08:22:20.000
2011-09-23 11:58:27.000
2011-09-24 09:00:48.000
2011-09-25 06:51:34.000
2011-09-26 06:09:05.000
2011-09-27 08:25:26.000
...
My question is, how can I get the average hour and minute? I want to know that what is the average start time for this job. (for example 07:22)
I tried something like this but didn't work:
select CAST(AVG(CAST(DATEPART(HH, START_TIME)AS float)) AS datetime) FROM
Thanks.
declare #T table(StartTime datetime)
insert into #T values
('2011-09-18 08:06:36.000'),
('2011-09-19 05:42:16.000'),
('2011-09-20 08:02:26.000'),
('2011-09-21 08:37:24.000'),
('2011-09-22 08:22:20.000'),
('2011-09-23 11:58:27.000'),
('2011-09-24 09:00:48.000'),
('2011-09-25 06:51:34.000'),
('2011-09-26 06:09:05.000'),
('2011-09-27 08:25:26.000')
;with C(Sec) as
(
select dateadd(second, avg(datediff(second, dateadd(day, datediff(day, 0, StartTime), 0), StartTime)), 0)
from #T
)
select convert(char(5), dateadd(minute, case when datepart(second, C.Sec) >= 30 then 1 else 0 end, C.Sec), 108)
from C
-----
08:08
Try this :
select CAST((SUM(DATEPART(HH, START_TIME) * 60 + DATEPART(MI, START_TIME))/COUNT(*))/60 AS VARCHAR(10)) + ':' + CAST((SUM(DATEPART(HH, START_TIME) * 60 + DATEPART(MI, START_TIME))/COUNT(*))%60 AS VARCHAR(10))
FROM.....

Sum of time in sql

I have a table like this...
create table test
(
dt datetime
)
In that table the datetime are as follows,
2011/02/02 12:55:00
2011/03/05 00:40:00
2011/02/03 00:12:00
I want to calculate sum hours,mi,ss
In a single Select query not sp.
If any one know please tell me.
Thanks ...
You could sum the times as seconds, then convert to hours, minutes and seconds:
select TotalSeconds / 3600 as [Hours], (TotalSeconds % 3600) / 60 as [Minutes], (TotalSeconds % 3600) % 60 as [Seconds]
from
(
select sum(datepart(hour, dt) * 3600) + sum(datepart(minute, dt) * 60) + sum(datepart(second, dt)) as TotalSeconds
from test
) t
Assuming the sum won't be more than 999 hours:
DECLARE #t TABLE(dt DATETIME);
INSERT #t SELECT '20110202 12:55'
UNION SELECT '20110305 00:40'
UNION SELECT '20110203 00:12';
WITH s AS
(
SELECT s = SUM(DATEDIFF(SECOND,
DATEADD(DAY, 0, DATEDIFF(DAY, 0, dt)), dt))
FROM #t
)
SELECT
s,
hhmmss = RIGHT('000' + RTRIM(s/3600), 3)
+ ':' + RIGHT('00' + RTRIM((s % 3600) / 60), 2)
+ ':' + RIGHT('00' + RTRIM((s % 3600) % 60), 2)
FROM s;
However, if what you are really storing is duration, why not store the number of seconds instead of wedging your data into an inappropriate data type that requires all kinds of workarounds to process properly?
Declare #Table Table
(
DateTimeCol DateTime
)
insert into #Table values ( '2011/02/02 12:55:00')
insert into #Table values ('2011/03/05 00:40:00')
insert into #Table values ('2011/02/03 00:12:00')
;with CTE As
(
--first of all find total seconds of datecolumn
--sum all seconds
Select SUM(
(datepart(hour,DateTimeCol)*60*60)+(datepart(minute,DateTimeCol)*60)+(datepart(second,DateTimeCol))
) As TotalSecond
From #Table
)
--devides with 3600 to get the total hours and then to 60 to get total minutes
Select CONVERT(VARCHAR(10),TotalSecond/3600)+ '.' +
CONVERT(VARCHAR(20),TotalSecond%3600/60) + '.' +
CONVERT(VARCHAR(20),TotalSecond%3600%60) AS [Time] --Total of Time
From CTE