How to convert HHMMSS to seconds using T-SQL - sql-server

SQL server table msdb.dbo.sysjobhistory returns run_time and run_duration as INTEGER value formatted as HHMMSS.
How to convert it to seconds?
Example:
163135 (16:31:35) becomes 59495 (seconds)

Meanwhile I figured out this formula:
SELECT DATEDIFF(SECOND, '00:00:00', FORMAT(run_duration, '00:00:00'))
FROM msdb.dbo.sysjobhistory

You can use modulo and integer division to separate the hours, minutes, and seconds, multiply by number of seconds in each result, then sum.
DECLARE #hms int = 163135;
SELECT #hms / 10000 * 3600
+ #hms % 10000 / 100 * 60
+ #hms % 100;
59495
To use this as a view, it's really not any different:
CREATE VIEW dbo.viewname
AS
SELECT <other cols>, run_duration,
run_duration_s = run_duration / 10000 * 3600
+ run_duration % 10000 / 100 * 60
+ run_duration % 100
FROM msdb.dbo.sysjobhistory
WHERE ...
If you don't like math so much, you can treat it like a string:
DECLARE #hms int = 163135;
DECLARE #s char(6) = RIGHT(CONCAT('000000', #hms), 6);
SELECT LEFT(#s, 2) * 60 * 60
+ SUBSTRING(#s, 3, 2) * 60
+ RIGHT(#s, 2);
59495
However, this latter solution may need some tweaking if you could have durations > 99 hours, since now the string will be 7 digits. Maybe safer to use:
DECLARE #hms int = 163135;
DECLARE #s char(24) = RIGHT(CONCAT(REPLICATE('0',24), #hms), 24);
SELECT LEFT(#s, 20) * 60 * 60
+ SUBSTRING(#s, 21, 2) * 60
+ RIGHT(#s, 2);
24 is a ludicrous example, but safe. The job would have had to start in 1990 to hit 10 digits today.

Related

How to convert int column in time "HH:MM" in SQL?

how can I convert int "Hour" and Int "Minute" into time and then get percentages of two different time?
to get total of time from int column I am using
Format((SUM([THOURS]) * 3600 + SUM([TMINUTES]) * 60 + SUM([TSECONDS])) / 3600,'00')+':'+Format((SUM([THOURS]) * 3600 + SUM([TMINUTES]) * 60 + SUM([TSECONDS])) % 3600/60,'00') as "Total Time"
I got the perfect time from the above query.
But now i wan to get percentage calculation from my two int "Hour" and Int "Minute" column table.
I have tried
DECLARE #MS INT = 235216
select cast(dateadd(ms, #MS, '00:00:00') AS TIME(3))
it's not working as my requirement.
Is anyone have an idea for same?
Convert your time fields into minutes, and then do the math on the minutes. This example uses two variables - you'd use your field names instead.
Declare
#Allotted As Time = '08:00'
, #Taken As Time = '06:00'
Select Cast(DateDiff(Minute, '00:00', #Taken) As Numeric(17, 2)) / DateDiff(Minute, '00:00', #Allotted) as Percent_Of_Allotted_Time
Perhaps this will help:
declare #A table
( xHours int, xMinutes int, xSeconds int,
yHours int, yMinutes int, ySeconds int )
insert into #A ( xHours, xMinutes, xSeconds, yHours, yMinutes, ySeconds ) values
( 7, 23, 59, 13, 44, 51 ),
( 0, 00, 12, 1, 07, 00 );
with A as ( select *,
3600 * xHours + 60 * xMinutes + xSeconds as xTotal,
3600 * yHours + 60 * yMinutes + ySeconds as yTotal
from #A ),
B as ( select *,
cast ( DATEADD(second,xTotal,'00:00:00') as time(0)) as xTime,
cast ( DATEADD(second,yTotal,'00:00:00') as time(0)) as yTime
from A ),
C as ( select *, 100*CAST(xTotal as float)/CAST(yTotal as float) as Usage from B )
select xTotal, yTotal, xTime, yTime, Usage from C
Result:
xTotal yTotal xTime yTime Usage
26639 49491 07:23:59 13:44:51 53.8259481521893
12 4020 00:00:12 01:07:00 0.298507462686567

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

Operand type clash: time is incompatible with int

In a table, I have a column (AvgWaitTime) which stores data value in seconds (Data Type: float), date wise. I have a function which performs some calculation using AvgWaitTime column and other few columns and returns a value in time format. I would to convert the value returned by the function (time format) into seconds (preferrably decimal, if not then int).
select
(datepart(HH, dbo.fnGetMonthlyAverageWaitTime(m.RDate) * 60 * 60) +
datepart(mi, dbo.fnGetMonthlyAverageWaitTime(m.RDate) * 60) +
datepart(s, dbo.fnGetMonthlyAverageWaitTime(m.RDate)))[MonthlyAverageWaitTime]
from TelephonyMTD m
Error: Operand type clash: time is incompatible with int
So, I tried to run this:
select
(datepart(HH, GetDate() * 60 * 60) +
datepart(mi, GetDate() * 60) +
datepart(s, GetDate()))
Now it says, Implicit conversion from data type datetime to int is not allowed. Use the CONVERT function to run this query. Which is true when I looked at the data type conversion chart, I came to know that conversion to int and float is now allowed.
Please advice.
The problem is you are trying to multiply a date/datetime by an integer which doesn't make sense:
GetDate() * 60 * 60
You could simply use DATEDIFF with seconds, to get the value in seconds:
SELECT DATEDIFF(SECOND, '00:00:00', dbo.fnGetMonthlyAverageWaitTime(m.RDate)) AS MonthlyAverageWaitTime
FROM TelephonyMTD AS m
QUICK EXAMPLE
SELECT t.AvgTime,
AvgTimeInSeconds = DATEDIFF(SECOND, '00:00:00', t.AvgTime)
FROM (VALUES
(CAST('00:01:15' AS TIME)),
(CAST('05:36:47' AS TIME))
) AS t (AvgTime);
Which gives:
+----------+------------------+
| AvgTime | AvgTimeInSeconds |
+----------+------------------+
| 00:01:15 | 75 |
| 05:36:47 | 20207 |
+----------+------------------+
Open and Close brackets are the one causing issue for the above error: Please try like below
SELECT (
( Datepart(HH, Getdate()) * 60 * 60 ) +
( Datepart(mi, Getdate()) * 60 ) +
Datepart(s, Getdate())
)
Try to use Below Syntax to convert seconds to day, hour, minute, seconds
DECLARE #sec INT = 86400;
SELECT
CAST(#sec /60/60/24 AS VARCHAR(12)) + ' Days,'
+ CAST(#sec /60/60 % 24 AS VARCHAR(12))+ ' Hours,'
+ CAST(#sec /60 % 60 AS VARCHAR(2)) + ' Minutes, '
+ CAST(#sec % 60 AS VARCHAR(2)) + ' Seconds.';

SQL Adding integer strings with zero values

I am trying to add strings which are integers. I have 201404 as input and I need it to be converted to 201503 so the only way to do this is to increase the year (2014) by 1 and decrease the month 02 by 1.
I have tried the below but the leading zero in the month does not seem to preserve:
DECLARE #YearMonth INT = 201404
, #left INT = 0
, #right INT = 0
SET #YearMonth = CAST(#YearMonth AS VARCHAR(6))
SET #left = CAST(LEFT(#YearMonth, 4) + 1 AS VARCHAR(MAX))
SET #right = RIGHT(#YearMonth, 2) - 1
SET #right = CAST(#right AS VARCHAR(2))
SET #right = RIGHT(('0' + CAST(#right AS VARCHAR(2))), 2)
PRINT #left
PRINT RIGHT('0' + LTRIM(RTRIM(#right)), 6)
Dealing with integer YYYYMM format can be difficult when adding and subtracting months. One method is to convert to a number of months, and then convert back to the format. So, this converts the value to a number of months
select (#YearMonth / 100) * 12 + (#YearMonth % 100)
Then we can add a number, such as 11 and convert back to the integer format:
select (( (#YearMonth / 100) * 12 + (#YearMonth % 100) + 11) / 12) * 100 +
( (#YearMonth / 100) * 12 + (#YearMonth % 100) + 11) % 12)
) as yyyymm
Another method that might be simpler is to use date arithmetic:
select dateadd(11, month, cast(#YearMonth as varchar(255)) + '01')
This returns a date. You can convert it back to the number as:
select (year(dateadd(11, month, cast(#YearMonth as varchar(255)) + '01')) * 100 +
month(dateadd(11, month, cast(#YearMonth as varchar(255)) + '01'))
) as yyyymm
Use REPLICATE
replicate('0', 2 - len(#right)) + #right
Just ran this:
DECLARE #YearMonth INT = 201404;
SELECT CONVERT(VARCHAR(6), DATEPART(YEAR, T.Data) + 1) + RIGHT(100 + DATEPART(MONTH, T.Data) -1, 2)
FROM (VALUES (CONVERT(VARCHAR(8), #YearMonth) + '01')) AS T(Data);
Result:
201503
It's going to pick month number and add 100 to it and then pick 2 right chars from it, so for instance you got 4, it becomes 104 and then RIGHT function picks last 2 characters, which are 04.
Checked with other params, seems fine:
DECLARE #YearMonth INT = 201411;
SELECT CONVERT(VARCHAR(6), DATEPART(YEAR, T.Data) + 1) + RIGHT(100 + DATEPART(MONTH, T.Data) -1, 2)
FROM (VALUES (CONVERT(VARCHAR(8), #YearMonth) + '01')) AS T(Data);
Result:
201510
I would convert implicitly to date, add 11 months and then format back as a string. The integer conversion would be implicit as well.
select format(dateadd(month, 11, str(#YearMonth) + '01'), 'yyyyMM')

Round *UP* to the nearest 100 in SQL Server

Is it possible to easily round a figure up to the nearest 100 (or 1000, 500, 200 etc.) in SQL Server?
So:
720 -> 800
790 -> 800
1401 -> 1500
The following should work. After reading your question, I'm not exactly sure what you want 100 to return. For this 100 returns 100.
select floor((X + 99) / 100) * 100;
This gives the following results:
0 -> 0
1 -> 100
99 -> 100
100 -> 100
101 -> 200
For rounding Up to the nearest thousand, try the following:-
select round(YourValue, -3)
One option would be to use the CEILING() function like this:
SELECT CEILING(#value/100.0) * 100
You may need to convert your value to a decimal first depending on its type.
Use CEILING function to round a figure up
DECLARE #Number DECIMAL, #RoundUp DECIMAL
SET #RoundUp = 100
SET #Number = 720
SELECT CEILING(#Number/#RoundUp)*#RoundUp
Try this:
select round(#value , -2);
It is very simple to round a number to any multiple of nearest 10 by using simply the ROUND function
for ex:
SELECT ROUND(number/1000,2)*1000
This will give you the nearest thousandth value.
This will work for the values with decimal also.
select floor((ceiling (#value) + 99) / 100) * 100;
There's no native function that will do this, but there are any number of simple math tricks that will. An example:
DECLARE #Foo int
SET #Foo = 720
print #Foo
print (#Foo + 100) % 100
PRINT #Foo - (#Foo + 100) % 100
You can use this code, assuming your amount is an int. If not you will need to cast, so you get integer division.
If amount % 100 != 0 Then
roundedAmount = ((amount / 100) * 100) + 100
Else
roundedAmount = amount
You might want to package this into a user defined function.
A generic solution - Use MOD to find the last 100th place and then add 100 to the result.
select (720 - MOD(720,100)) + 100 from dual;
If you need the next 80th place, just replace any "100" with "80".
In addition to Gray's answer,
I'd use the following inline function:
CREATE FUNCTION dbo.udf_RoundNearest
(
#Number bigint,
#RoundNearest bigint,
#Direction int
)
RETURNS TABLE AS
RETURN
SELECT CASE WHEN #RoundNearest>=#Number THEN #Number
ELSE
(
(#Number + CASE
WHEN #Direction = 0 --Round Down
THEN 0
ELSE CASE WHEN #Number % #RoundNearest = 0 THEN 0 ELSE #RoundNearest END
END) / #RoundNearest) * #RoundNearest
END Number
Parameter Definition:
#Number - the number you need to round
#RoundNearest 10th, 100th , 1000th etc
#Direction 0-> round down, 1-> round up
using the function:
SELECT * FROM dbo.udf_RoundNearest (1965,100,1) --> 2000
SELECT * FROM dbo.udf_RoundNearest (1359,100,0) --> 1300
SELECT * FROM dbo.udf_RoundNearest (1999,10,0) --1990
SELECT * FROM dbo.udf_RoundNearest (80,100,0) --> 80 (if the #number parameter is less or equal the #RoundNearest parameter the result will be the #number itself
it can also be used as apply it versus a table
such as:
;with tmp (Value) as
(select 1236 union all select 6584 union all select 9999)
select t.*, fn.Number
from tmp t
cross apply dbo.udf_RoundNearest (Value,100,0) fn
/*Result Set
Value Number
1236 1200
6584 6500
9999 9900*/
This worked fine for me.
Round(#value/100, 0) * 100
It works fine for integer value:
#roundUpValue = ((#intValue / 1000) + 1) * 1000
#roundDownValue = (#intValue / 1000) * 1000
For example
declare #intValue as int = 1934
select ((#intValue / 1000) + 1) * 1000 as roundUp
select (#intValue / 1000) * 1000 as roundDown
If you want to round up to the nearest 500 then
select ((#intValue / 500) + 1) * 500 as roundUp
Select round(value/100,0)*100
Whatever number you want to round to, just post that instead of 100 here.
i have create a function in mssql it can help you
CREATE function dbo.roundup
(
#numbr decimal(18,2),
#frac decimal(18,2)
)
RETURNS decimal(18,2)
AS
BEGIN
DECLARE #result decimal(18,2)
set #result = ceiling(#numbr/#frac)*#frac
RETURN #result
END
GO

Resources