I have a column called TimeSpent of type Float.
It contains values (i.e. 2.50, 1.25, 3.75, 5.60 )
I need to convert these hour values to appropriate hour values like (2:30, 1:15, 3:45 ,5:36) etc)
How can this be done?
Try this Query
select
time_decimal
,cast(cast(cast(time_decimal as int) as varchar)+
':'+cast(cast((time_decimal - cast(time_decimal as int)) * 60 as int) as varchar)+
':'+cast(cast(((time_decimal - cast(time_decimal as int)) * 60-
cast((time_decimal - cast(time_decimal as int)) * 60 as int)) * 60 as int) as varchar) as time) as real_time
from time1
SQL FIDDLE
Just do the math: the hour you can get by casting to int, for example. To get the minutes, multiply the decimal part by 60, etc.
A quick and dirty way to do it in a single query could be:
declare #d float
set #d = 1.54
select cast(#d as int) h,
cast((#d - cast(#d as int)) * 60 as int) m,
cast(((#d - cast(#d as int)) * 60
- cast((#d - cast(#d as int)) * 60 as int)) * 60 as int) s
Assuming you have created already a column with datatype time, you update your table by concatenating the left of TimeSpent till the dot and the part right of the dot multiplied by 60.
SQL Server 2012:
UPDATE yourTable SET
newTimeColumn = CONCAT(CAST(TimeSpentFloat AS INT), ':', (TimeSpentFloat - CAST(TimeSpentFloat AS INT)) * 60);
SQL Server 2008 and lower:
SELECT
CAST(CAST(2.75 AS INT) AS CHAR) + ':' + CAST((2.75 - CAST(2.75 AS INT)) * 60 AS CHAR);
See it working in an sqlfiddle.
Related
In my database, I have a table with a column of type Float which represents the total work hours. I have to sum this value over all rows.
I can't use sum function, because 08.03 = 08 hour, 03 minute.
For example:
00.55 + 00.51=> 01.06
but I want
00.55 + 00.51 => 01.46
My query
Declare #TEMP1 table (TotalHours float)
insert into #TEMP1(TotalHours)
select ol.HrWork TotalHours
from OTLog ol
where EmployeeId = 2048
Declare #attCount int
Declare #attSum int
set #attSum = 0;
set #attCount = (select count(*) from #TEMP1)
print #attCount
while (#attCount <> 0)
begin
set #attSum = #attSum + (select Top 1 (LEFT(TotalHours,1)*60)+(RIGHT(TotalHours,2)) TotalHours from #TEMP1);
delete top(1) from #TEMP1;
set #attCount = #attCount - 1;
print #attSum;
end
print #attSum
select *
from OTLog
where EmployeeId = 2048
Any thoughts would be appreciated.
should use proper data type for storing time and not float
You need to break the float time into hour & minute. sum() it and convert back to your float format
select convert(int, total_minute / 60) + (total_minute % 60) / 100.0
from
(
select total_minute = sum(convert(int ,([hour] * 60) + [minute]))
from
(
select hour = floor(TotalHours), minute = convert(int, TotalHours * 100) % 100
from #TEMP1
) d
) d
You can try to use left(col1,2) to get hour number,right(col1,2) get minute number.
then use SUM to get totle hours and minutes in a subquery.
Then use DATEADD to add time value.
CREATE TABLE T(
col1 VARCHAR(10)
);
INSERT INTO T VALUES ('00.55');
INSERT INTO T VALUES ('00.51');
Query 1:
select FORMAT(DATEADD(minute,m,0)+ DATEADD(hour,h,0),'HH:mm:ss')
from (
SELECT SUM(CAST(left(col1,2) AS INT)) h ,SUM(CAST(right(col1,2) AS INT)) m
FROM T
) t1
Results:
| |
|----------|
| 01:46:00 |
Few issues with your problem:
first, float is not good choice for storing time information, look at date, time, datetime, timestamp, datetime2 - choose one of these, it will prevent such problems from occuring plus you have methods in SQL to work with such datatypes.
second - float is just approximation!, decimal stores exact values, you must be aware of that,
third - you need to be careful when dealing with decimal values in SQL Server, see Precision, scale, and Length (Transact-SQL) and this thread: Why is 199.96 - 0 = 200 in SQL?
After all, I can suggest this query to solve your problem:
select id,
sum(hours) + floor(sum(minutes) / 60) hours,
sum(minutes) % 60 minutes
from (
select id,
floor([time]) [hours],
cast([time] * 100 as int) % 100 [minutes]
from tblFloat
) a group by id
See this SQL fiddle, there you can test difference between using float and decimal (see the differences in a queries).
I have table name tblAttend in which one column named WorkHrs is of datatype varchar.
The result of simple select query is
I sum this column's value and get result in seconds my query is
select sum(DATEDIFF(SECOND, '0:00:00', WorkHrs ))
from tblAttend
and it shows this output:
Now the issue is, when sum of WorkHrs is greater than 24 hours it will throw an error:
What can you suggest to get around this problem? Thanks in advance
Try splitting each time into its component parts by converting the time to a string and then multiplying by the number of seconds relevant to each part.
Data conversion to integer is implicit
select Sum(Left(WorkHrs,2) * 3600 + substring(WorkHrs, 4,2) * 60 + substring(WorkHrs, 7,2))
from tblAttend
Try:
DECLARE #DURATION TIME = '01:43:24'
SELECT DATEDIFF(SECOND, '1/1/1900', CONVERT(DATETIME, #DURATION))
Try this:
SELECT DATEDIFF(SECOND, CONVERT(DATE,GETDATE()), GETDATE())
I have implemented the following function to use it in the management of my projects :
/****** Object: UserDefinedFunction [dbo].[Seconds] Script Date: 10/6/2017 12:00:22 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*
select [dbo].[Seconds]('24:00:00'),(24*3600)
select [dbo].[Seconds]('102:56:08'),(102*3600+56*60+8)
*/
ALTER FUNCTION [dbo].[Seconds] (#Time as varchar(50))
RETURNS int
BEGIN
declare #S int, #H int
set #H=cast(SUBSTRING(#Time,1,CHARINDEX(':',#Time)-1) as int)
IF #H<24
set #S=DATEDIFF(SECOND, '0:00:00', #Time)
ELSE BEGIN
set #H=#H-23
set #Time = '23'+SUBSTRING(#Time,CHARINDEX(':',#Time),LEN(#Time)-2)
set #S = (#H*3600)+DATEDIFF(SECOND, '0:00:00', #Time)
END
RETURN #S
END
You may try like this:
SELECT Sec=SUM((DATEPART(HOUR,column name)*3600)+(DATEPART(MINUTE,column name)*60)+(DATEPART(Second,column name)))
FROM [TableName]
You need to convert your WorkHrs to DATETIME first, then perform the DATEDIFF:
WITH Cte(WorkHrs) AS(
SELECT CAST('02:29:11' AS VARCHAR(10)) UNION ALL
SELECT CAST('21:00:00' AS VARCHAR(10)) UNION ALL
SELECT CAST('25:20:02' AS VARCHAR(10))
),
CteConvert(dt) AS(
SELECT
DATEADD(
SECOND,
CAST(SUBSTRING(WorkHrs, 7, 2) AS INT),
DATEADD(
MINUTE,
CAST(SUBSTRING(WorkHrs, 4, 2) AS INT),
DATEADD(
HOUR,
CAST(SUBSTRING(WorkHrs,1, 2) AS INT),
0
)
)
)
FROM Cte
)
SELECT
SUM(DATEDIFF(SECOND, 0, dt)),
-- Formatted to hh:mm:sss
RIGHT('0' + RTRIM(CONVERT(CHAR(2), SUM(DATEDIFF(SECOND, 0, dt)) / (60 * 60))), 2) + ':' +
RIGHT('0' + RTRIM(CONVERT(CHAR(2), (SUM(DATEDIFF(SECOND, 0, dt)) / 60) % 60)), 2) + ':' +
RIGHT('0' + RTRIM(CONVERT(CHAR(2), SUM(DATEDIFF(SECOND, 0, dt)) % 60)),2)
FROM CteConvert
;with cte as (
select
total =Sum(Left(WorkHrs,2) * 3600 + substring(WorkHrs, 4,2) * 60 + substring(WorkHrs, 7,2))
from tblAttend
)
select
total [Total Time in Seconds],
(total / 3600) [Total Time Hour Part],
((total % 3600) / 60) [Total Time Minute Part],
(total % 60) [Total Time Second Part]
from cte
I think you can isolate each part of the time (hour, minute and second) and than sum what you need, please take a look:
declare #tbl table(WorkHrs VARCHAR(8))
insert into #tbl(WorkHrs) values ('02:29:11')
insert into #tbl(WorkHrs) values ('25:00:11')
-- Sum in minutes
SELECT TRY_CAST(([HOURS] * 60) + [MINUTES] + ([SECOND] / 60) AS INT) as TotalInMinutes
FROM (
SELECT
-- Use this aproach to get separated values
SUBSTRING(WorkHrs,1,CHARINDEX(':',WorkHrs)-1) AS [HOURS],
SUBSTRING(WorkHrs,4,CHARINDEX(':',WorkHrs)-1) AS [MINUTES],
SUBSTRING(WorkHrs,7,CHARINDEX(':',WorkHrs)-1) AS [SECOND] -- probably you can ignore this one
FROM #tbl
)
tbl
-- Or try to sum in seconds
SELECT TRY_CAST(([HOURS] * 3600) + ([MINUTES] * 60) + [SECOND] AS INT) as TotalInSeconds
FROM (
SELECT
-- Use this aproach to get separated values
SUBSTRING(WorkHrs,1,CHARINDEX(':',WorkHrs)-1) AS [HOURS],
SUBSTRING(WorkHrs,4,CHARINDEX(':',WorkHrs)-1) AS [MINUTES],
SUBSTRING(WorkHrs,7,CHARINDEX(':',WorkHrs)-1) AS [SECOND]
FROM #tbl
)
tbl
It will return like this to you:
I hope it can help
You can simply use the TIME_TO_SEC function:
SELECT TIME_TO_SEC(WorkHrs) FROM tblAttend;
One of the columns of my SQL Server table is mm:ss of varchar type where mm = minutes and ss = seconds.
I need to get the average of that column.
Should I convert that column to datetime format first? If so can you tell me how? If not can you tell me what I should do?
Here is my failed attempt to convert it to datetime :
SELECT CONVERT(DATETIME, '2014-01-01 '+Pace+':00', 108)
Where pace is a varchar like 23:05
If you want the average, I would convert the column to number of seconds and work with that:
select avg(pace_secs) as average_in_seconds
from (select cast(left(pace, 2) as int) * 60 + cast(right(pace, 2) as int) as pace_secs
from t
) t;
If you want this back in the format, then you can do:
select right('00' + cast(avg(pace_secs) / 60 as int), 2) + ':' +
right('00' + avg(page_secs) % 60), 2)
from (select cast(left(pace, 2) as int) * 60 + cast(right(pace, 2) as int) as pace_secs
from t
) t;
declare #pace varchar(20) = '23:05 ';
SELECT cast( '2014-01-01 '+cast(#pace as varchar(5))+':00' as datetime)
For SQL2012 and later
SELECT
FORMAT(DATEADD(second,AVG(DATEDIFF(second,0,'00:'+[Pace])),0),'mm:ss')
FROM MyTable
Is there a easy way to format a float number in hours in Ms SQL server 2008?
Examples:
1.5 -> 01:30
9.8 -> 09:48
35.25 -> 35:15
Thanks a lot.
I like this question!
DECLARE #input float = 1.5;
DECLARE #hour int = FLOOR(#input);
DECLARE #minutes int = (SELECT (#input - FLOOR(#input)) * 60);
SELECT RIGHT('00' + CONVERT(varchar(2), #hour), 2) + ':' + RIGHT('00' + CONVERT(varchar(2), #minutes), 2);
SELECT SUBSTRING(CONVERT(NVARCHAR, DATEADD(MINUTE, 1.5*60, ''), 108), 1, 5)
This works by:
starting from the "zero" date
adding 1.5 x 60 minutes (i.e. 1.5 hours)
formatting the result as a time, hh:mm:ss (i.e. format "108")
trimming off the seconds part
It is necessary to use 1.5 x 60 minutes instead of 1.5 hours as the DATEADD function truncates the offset to the nearest integer. If you want high-resolution offsets, you can use SECOND instead, suitable scaled (e.g. hours * 60 * 60).
Sure. Easy, but not exactly...straightforward:
declare #hours float
set #hours = -9.8
select substring('- ',2+convert(int,sign(#hours)),1) -- sign
+ right('00' + convert(varchar, floor(abs(#hours))) , 2 ) -- hours component
+ ':' -- delimiter
+ right('00' + convert(varchar,round( 60*(abs(#hours)-floor(abs(#hours))) , 0 ) ) , 2 ) -- minutes
Another option that will give the correct result. You might need to tweak it to round minutes and to ensure that both fields are 2 digits wide.
declare #hours float
set #hours = -9.8
select convert(varchar, datediff(minute,dateadd(minute,#hours*60,convert(datetime,'')),'') / 60 )
+ ':' + convert(varchar, datediff(minute,dateadd(minute,#hours*60,convert(datetime,'')),'') % 60 )
WITH m AS
SELECT Minutes = CAST(#hours * 60 AS int)
)
SELECT CAST(Minutes / 60 AS varchar) + ':' + RIGHT(100 + Minutes % 60, 2)
FROM m
select dateadd(MINUTE, cast((8.18 % 1) * 60 as int), dateadd(hour, cast(8.18 as int), convert(varchar(10), getdate(), 10)))
HI guys,
My litle problem goes like this :
I have this columns : PHONE_NR , TIME ( time field ), Meaning the calling telephone number and call duration. I need to group phone nr and sum the minutes. Filds looks like this :
nr time
726028xxx 00:07:07
735560css 00:07:37
726028xxx 00:07:55
SELECT PHONE_NR, SUM(DATEPART(minute, TIME)) FROM [table] GROUP BY PHONE_NR;
As far as I know this should work for both SQL Server DATETIME and the 2008 TIME data-types.
Example:
DECLARE #tbl TABLE
(
phone_nr varchar(10),
call_time TIME
);
INSERT INTO #tbl VALUES ('726028xxx', '00:07:07');
INSERT INTO #tbl VALUES ('735560css', '00:07:37');
INSERT INTO #tbl VALUES ('726028xxx', '00:07:55');
SELECT phone_nr, SUM(DATEPART(minute, call_time)) AS total_call_time FROM #tbl GROUP BY phone_nr;
Results in:
phone_nr | minutes
726028xxx | 14
735560css | 7
EDIT:
This version is identical to the above, except it also takes into account the seconds and hours (e.g. 1hr 7min 07secs = 67.117 minutes) so it's much more accurate.
SELECT
phone_nr,
SUM(CAST(DATEPART(second, call_time) + (DATEPART(minute, call_time) * 60) + (DATEPART(hour, call_time) * 3600) AS decimal) / 60) AS total_call_time
FROM
#tbl
GROUP BY
phone_nr;
Results in the following if the first record was 01:07:07.
phone_nr | minutes
726028xxx | 75.033332
735560css | 7.616666
You can use DATEDIFF to get the total number of minutes that have passed since time "zero"
SELECT
[PHONE_NR],
SUM(DATEDIFF(minute, '00:00:00', [TIME]))
FROM
[YourTable]
GROUP BY
[PHONE_NR]
declare #v1 varchar(50)
declare #v2 varchar(50)
set #v1='03:10'
set #v2='01:50'
--select cast(left(v1,2) as int) + cast(left(v2,2)as int)
select
cast(
cast(left(#v1,2) as int) + cast(left(#v2,2)as int)
+(cast(right(#v1,2) as int) + cast(right(#v2,2) as int))/60 as varchar)
+':'+cast(( cast(right(#v1,2) as int) + cast(right(#v2,2) as int))%60 as varchar)