I need to convert minutes into hours in sql server.
I used following logic to do it.
CAST(REPLACE(LEFT(CONVERT(varchar(10), DATEADD(MINUTE, 19.80 *100, ''), 114),5),':','.') AS Decimal(5,2)) AS tpschedhours
My expected Output is 33 hours (1980 minutes in hours)
But I got output as 9 hours. I have found that, the issue occurs because DATEADD(MINUTE,1980, '') returns ouptut as 1900-01-02 09:00:00.000 (One day + 9 hours). But I need the Output as Hours value i.e 33 hours
Thanks for the help
SELECT CONVERT(varchar(5),
DATEADD(minute, DATEDIFF(minute, #StartDate, #EndDate), 0), 114)
You can try in following:
DECLARE #time INT = 1980
SELECT LEFT(CONVERT(VARCHAR(10), DATEADD(MINUTE, #time / 60 + (#time % 60), ''),114),5)
I Got the solution from the answers.
SELECT CAST((CAST(((2.72) *100)AS INT) / 60 )+ (CAST((2.72 *100)AS INT) % 60) / 100.0 AS DECIMAL(5,2)).
thanks tinka and Stanislovas Kalašnikovas
Related
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 can I add hours and minutes in a single query?
I tried this
Select DATEADD(hh,23.59,CAST('2016-07-08' AS DATETIME))
I need to ad 23 hours and 59 minutes, but my code only adds the hours. Why?
How about this?
Select DATEADD(minute, 23*60 + 59, CAST('2016-07-08' AS DATETIME))
EDIT:
If you are getting a float/decimal value such as 23.59, then you can do:
Select DATEADD(minute, FLOOR(#hhmm) * 60 + (#hhmm - FLOOR(#hhmm)) * 100, CAST('2016-07-08' AS DATETIME))
Note: You can also use:
Select DATEADD(minute, FLOOR(#hhmm) * 60 + (#hhmm % 1) * 100, CAST('2016-07-08' AS DATETIME))
But I find this usage of the modulo operator slightly off-kilter.
Use the below code for adding time part to a date.
SELECT DATEADD(Day, DATEDIFF(Day, 0, CAST('2016-07-08' AS DATETIME)), '23:59:00.000')
You can also use DATEADD() twice:
Select DATEADD(minute,59,DATEADD(hh,23,CAST('2016-07-08' AS DATETIME)))
The datepart argument, in your case hh, is part of date to which an integer number is added. So the DATEADD function just ignores any fractional part of your input.
To get result you want, you need to either use DATEADD twice, adding 23 hours and then 59 minutes, or add one day to your date and subtract 1 minute, like this:
Select DATEADD(MI, -1, CAST('2016-07-08' AS DATETIME) + 1)
See also Microsoft's documentation on DATEADD.
another method : you can do by adding one day and then substract minute
Output is same
select DATEADD(minute, -1, DATEADD(DAY, 1,CAST('2016-07-08' AS DATETIME)))
I have multiple records as workinghours of employee as
02:10:00
03:00:00
12:00:00
12:34:56
Now i need to add these record and want to display in
`hh:mm:ss`
Format. I used following query but it only works when sum of record less than 24 hours but record may be greater than 24 hours.
SELECT CAST(DATEADD(MILLISECOND,
SUM(DATEDIFF(MILLISECOND, '00:00:00.000'
, CAST(WorkHrs AS TIME))), '00:00:00.000') AS TIME) AS Total_Time
FROM tblAttend
I spend more than 4 hours on google to find solution but got no success anymore.
Datatype of workinghour column is varchar .
The time data type has an explicit range only up to 24 hours (see here).
So, I think you are basically stuck with doing the conversion yourself. It is ugly, but looks something like:
SELECT RIGHT('00' + CAST(SUM(DATEDIFF(MILLISECOND, '00:00:00.000', CAST(WorkHrs AS TIME))), '00:00:00.000')/(60*60) AS VARCHAR(255)), 2)
) +
RIGHT('00' + CAST((SUM(DATEDIFF(MILLISECOND, '00:00:00.000', CAST(WorkHrs AS TIME))), '00:00:00.000')/60 % 60) AS VARCHAR(255)), 2) +
RIGHT('00' + CAST(SUM(DATEDIFF(MILLISECOND, '00:00:00.000', CAST(WorkHrs AS TIME))), '00:00:00.000') % 60 AS VARCHAR(255)), 2)
)
Merhaba Waqas,
Could you please try following SQL CTE Select statement,
It returns hours value more than 24, for this case it was 29 I guess.
Please check time calculation on SQL Server, this select is adapted from there
;with cte as (
select
userid,
total = sum( DATEPART(ss,period) + 60 * DATEPART(mi,period) + 3600 * DATEPART(hh,period) )
from WorkingHours
group by userid
)
select
userid,
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 hope it helps you
I need to calculate the total length in terms of Hours, Minutes, Seconds, and the average length, given some data with start time and end time.
For example the result must be something like 45:15:10 which means 45 hours 15 min 10 sec, or 30:07 for 30 min 07 sec.
We're using SQL Server 2008 R2 and the conversion failed when time is more than 24:59:59. Any idea of how I could do this?
For information, the columns in the table are Id, StartDateTime, EndDateTime, etc. I need to make a monthly report which contains the recordings count of the month, the total length of these records, and the average length. I'd like to know if there is an easy way to perform all of this.
You shouldn't be converting to time - it is meant to store a point in time on a single 24h clock, not a duration or interval (even one that is constrained on its own to < 24 hours, which clearly your data is not). Instead you can take the datediff in the smallest interval required (in your case, seconds), and then perform some math and string manipulation to present it in the output format you need (it might also be preferable to return the seconds to the application or report tool and have it do this work).
DECLARE #d TABLE
(
id INT IDENTITY(1,1),
StartDateTime DATETIME,
EndDateTime DATETIME
);
INSERT #d(StartDateTime, EndDateTime) VALUES
(DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
(GETDATE() , DATEADD(MINUTE, 22, GETDATE())),
(DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())),
(DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));
;WITH x AS (SELECT id, StartDateTime, EndDateTime,
d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
FROM #d
)
SELECT id, StartDateTime, EndDateTime,
[delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
[avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;
Results:
id StartDateTime EndDateTime delta_HH:MM:SS avg_HH:MM:SS
-- ------------------- ------------------- -------------- ------------
1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00 42:10:33
2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00 42:10:33
3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00 42:10:33
4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14 42:10:33
This isn't precisely what you asked for, as it won't show just MM:SS for deltas < 1 hour. You can adjust that with a simple CASE expression:
;WITH x AS (SELECT id, StartDateTime, EndDateTime,
d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
FROM #d
)
SELECT id, StartDateTime, EndDateTime,
[delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN
CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
+ RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
[avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN
CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
+ RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;
This query changes the delta column in the 2nd row in the above result from 0:22:00 to 22:00.
I slightly modified Avinash's answer as it may end with error if difference is too big. If you need only HH:mm:ss it is sufficient to distinguish at seconds level ony like this:
SELECT CONVERT(time,
DATEADD(s,
DATEDIFF(s,
'2018-01-07 09:53:00',
'2018-01-07 11:53:01'),
CAST('1900-01-01 00:00:00.0000000' as datetime2)
)
)
SELECT CONVERT(time,
DATEADD(mcs,
DATEDIFF(mcs,
'2007-05-07 09:53:00.0273335',
'2007-05-07 09:53:01.0376635'),
CAST('1900-01-01 00:00:00.0000000' as datetime2)
)
)
If you want to do averages, then the best approach is to convert to seconds or fractions of a day. Day fractions are convenient in SQL Server, because you can do things like:
select avg(cast(endtime - starttime) as float)
from t
You can convert it back to a datetime using the reverse cast:
select cast(avg(cast(endtime - starttime as float) as datetime)
from t
The arithmetic to get the times in the format you want . . . that is a pain. You might consider including days in the final format, and using:
select right(convert(varchar(255), <val>, 120), 10)
To get the hours exceeding 24, here is another approach:
select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6)
It uses convert for minutes and seconds, which should be padded with 0s on the left. It then appends the hours as a separate value.
Starting in SQL SERVER 2012, you don't need to use DATEDIFF function. You can use FORMAT function to achieve what you want:
SELECT
FORMAT(CONVERT(TIME, [appoitment].[Start] - [appointment].[End]), N'hh\:mm') AS 'Duration'
FROM
[tblAppointment] (NOLOCK)
A way that avoids overflows and can include days and go all the way to milliseconds in the output:
DECLARE #startDate AS DATETIME = '2018-06-01 14:20:02.100'
DECLARE #endDate AS DATETIME = '2018-06-02 15:23:09.000'
SELECT CAST(DATEDIFF(day,'1900-01-01', #endDate - #startDate) AS VARCHAR) + 'd ' + CONVERT(varchar(22), #endDate - #startDate, 114)
The above will return
1d 01:03:06:900
And, off course, you can use the formatting of your choice
SQL Supports datetime substraction which outputs a new datetime relative to the MIN date (for instance 1900-01-01, you can probably get this value from some system variable) This works better than DATEDIFF, because DATEDIFF will count ONE for each "datepart boundaries crossed", even if the elapsed time is less than a whole datapart. Another nice thing about this method is that it allows you to use the date formatting conversions.
If days is the (positive) number of days, like 0.5 for 12 hours, use this expression to format it as a proper duration:
CONVERT(varchar(9), FLOOR(days * 24)) + RIGHT(CONVERT(char(19), CAST(days AS datetime), 120), 6)
Excel will understands values up to 9999:59:59 when pasted. There apply a custom format: [h]:mm:ss in the English version ([u]:mm:ss for Dutch).
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.....