Cast varchar to time and SUM in SQL generates Error - sql

I try to cast time in HH:MM Format it works fine but when i insert time above 23 hours i.e 24:0 it generates error
"The conversion of a varchar data type to a datetime data type resulted in an out-of-range value. "
Below is code
CREATE TABLE mytable
(
timeduration varchar(25)
)
INSERT INTO mytable VALUES ('05:30')
INSERT INTO mytable values ('24:0')
INSERT INTO mytable values ('04:33')
-- OUTPUT SHOULD BE 34:3 MINUTES
select CAST
(
(SUM (datepart(hh, convert (varchar, timeduration, 108))) +
(sum(datepart(mi, convert (varchar, timeduration, 108)))/60) ) AS VARCHAR(2)
)
+ ':' +
CAST
(
sum(datepart(mi, convert (varchar, timeduration, 108))) - 60 * (sum(datepart(mi, convert (varchar, timeduration, 108)))/60)
as VARCHAR(2))
from mytable

Your problem is '24:00', Here should be '00:00' if you want it to work.
But then you have to add case expressions to you query. I suggest you to rewrite as:
DECLARE #mytable TABLE
(
timeduration VARCHAR(25)
)
INSERT INTO #mytable
VALUES ( '05:30' )
INSERT INTO #mytable
VALUES ( '24:0' )
INSERT INTO #mytable
VALUES ( '04:33' );
WITH cte
AS ( SELECT SUM(CAST(SUBSTRING(timeduration, 1, CHARINDEX(':', timeduration) - 1) AS INT)) AS Hours ,
SUM(CAST(SUBSTRING(timeduration, CHARINDEX(':', timeduration) + 1, 5) AS INT)) AS Minutes
FROM #mytable
)
SELECT CAST(Hours + Minutes / 60 AS NVARCHAR(20)) + ':' + CAST(Minutes % 60 AS NVARCHAR(20)) AS Duration
FROM cte
Output:
Duration
34:3

Related

Convert int 20171116101856 to yyyymmddhhmmss format to be used in datediff function

So I have this table that has date columns in int type.
last_run_date | last_run_time
20171116 | 100234
Im trying to convert this two values into a datetime to be used in datediff statement.
this is my statement
SELECT 1
FROM V_Jobs_All_Servers vjas
WHERE JobName='DailyReports_xxxx' and Step_Name='xxxx'
and DATEDIFF(hour, Convert(varchar,STUFF(STUFF(STUFF(STUFF(STUFF(cast(
Convert(varchar(100),vjas.last_run_date) + Convert(varchar(100),vjas.last_run_time) as varchar)
,5,0,'-'),8,0,'-'),11,0,' '),14,0,':'),17,0,':')), Getdate()) <3
This works but only when the last_run_time value is in two digits hour format
101216, but whenever its one digit hour 91316 it fails with the following error,
The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
I am on SQL Server 2005
If you're getting this value from msdb.dbo.sysjobsteps, there's a built-in function, msdb.dbo.agent_datetime(), to convert last_run_date and last_run_time to a datetime already:
select job_id,
step_id,
step_name,
msdb.dbo.agent_datetime(nullif(last_run_date,0),nullif(last_run_time,0)) as last_run_datetime
from msdb.dbo.sysjobsteps
It is an undocumented function. However, at least in my version of SQL Server (2012), that function has this definition:
CREATE FUNCTION agent_datetime(#date int, #time int)
RETURNS DATETIME
AS
BEGIN
RETURN
(
CONVERT(DATETIME,
CONVERT(NVARCHAR(4),#date / 10000) + N'-' +
CONVERT(NVARCHAR(2),(#date % 10000)/100) + N'-' +
CONVERT(NVARCHAR(2),#date % 100) + N' ' +
CONVERT(NVARCHAR(2),#time / 10000) + N':' +
CONVERT(NVARCHAR(2),(#time % 10000)/100) + N':' +
CONVERT(NVARCHAR(2),#time % 100),
120)
)
END
You are massively over complicating this, just pad your time value with a leading 0 and convert from there:
declare #t table(last_run_date int, last_run_time int);
insert into #t values(20171116,90234),(20171116,100234);
select last_run_date
,last_run_time
,convert(datetime,cast(last_run_date as nvarchar(8))
+ ' '
+ stuff(stuff(right('0' + cast(last_run_time as nvarchar(6))
,6)
,5,0,':')
,3,0,':')
,112) as DateTimeData
from #t
Output:
+---------------+---------------+-------------------------+
| last_run_date | last_run_time | DateTimeData |
+---------------+---------------+-------------------------+
| 20171116 | 100234 | 2017-11-16 09:02:34.000 |
| 20171116 | 100234 | 2017-11-16 10:02:34.000 |
+---------------+---------------+-------------------------+
Here's an ugly way...
declare #table table (last_run_date int, last_run_time int)
insert into #table
values
(20171116,100234),
(20171116,91316)
select
cast(cast(cast(last_run_date as varchar) as datetime) + ' ' + stuff(stuff(last_run_time,len(last_run_time) - 1,0,':'),len(stuff(last_run_time,len(last_run_time) - 1,0,':')) - 4,0,':') as datetime)
from #table
DECLARE #temp TABLE (last_run_date int, last_run_time int)
INSERT INTO #temp VALUES (20171116, 100234)
SELECT convert(datetime,CAST(last_run_date as varchar))
+ Convert(time, Dateadd(SECOND, Right(last_run_time,2)/1
,Dateadd(MINUTE, Right(last_run_time,4)/100
,Dateadd(hour, Right(last_run_time,6)/10000
,'1900-01-01'
)
)
)
) [DateConverted]
FROM #temp
Produces Output:
DateConverted
2017-11-16 10:02:34.000
You can see how this works by doing each part individually.
SELECT Dateadd(hour, Right(last_run_time,6)/10000
,'1900-01-01')
FROM #temp
Gives the hours position.
SELECT Dateadd(MINUTE, Right(last_run_time,4)/100
,Dateadd(hour, Right(last_run_time,6)/10000
,'1900-01-01'))
FROM #temp
Gives the hours plus minutes position.
Etc.

SQL conversion from varchar to datetime

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

convert 0000:00:00.00 datetime sql

I have varchar column where the datetime is saved and i have some date times with the normal form 00:00:00.00 which i can convert to date time and some others with the following format 0000:00:00.00 which i can't convert them. how can i solve this problem? I tried to convert it but i get an error for those values.
select (DATEPART(HOUR, (SELECT CONVERT(datetime,time,121) FROM table
) ) * 3600) + (DATEPART(MINUTE, (SELECT CONVERT(datetime,time,121)
FROM table) ) * 60) + (DATEPART(SECOND, (SELECT
CONVERT(datetime,time,121) FROM table ) ) ))
Based on the information provided and the assumption that 0000:00:00.00 = HHHH:MM:SS:NN
DECLARE #t table (
blah varchar(20)
);
INSERT INTO #t (blah)
VALUES ('0:00:00.00')
, ('0000:00:00.00')
, ('0000:01:37.61');
SELECT blah
, hours
, minutes
, seconds
, milliseconds
, DateAdd(ms, milliseconds, DateAdd(ss, seconds, DateAdd(mi, minutes, DateAdd(hh, hours, 0))))
FROM (
SELECT blah
, Cast(left_part As int) As hours
, Cast(SubString(right_part, 1, 2) As int) As minutes
, Cast(SubString(right_part, 4, 2) As int) As seconds
, Cast(Left(SubString(right_part, 7, 3) + '000', 3) As int) As milliseconds -- padded to 3 characters (trailing zeroes)
FROM (
SELECT blah
, SubString(blah, 0, CharIndex(':', blah)) As left_part
, SubString(blah, CharIndex(':', blah) + 1, 20) As right_part -- FYI 20 = length of varchar field
FROM (
SELECT blah
, CharIndex(':', blah) + 1 As colon
FROM #t
) As find_the_first_colon
) As split_the_string_by_first_colon
) As work_out_component_parts;

How to sum set of period times in specific format

If I have result set like that :
Work_hour(hh:mm)
10:24
12:59
06:28
where Work_hour is of type varchar
How to sum those hours and minutes with the same format ?
SELECT CAST(FLOOR(TMP1.MINS/60) AS VARCHAR) + ':' + CAST((TMP1.MINS % 60) AS VARCHAR) FROM (
SELECT SUM (CAST(LEFT(time_column, 2) AS INT) * 60 + CAST(RIGHT(time_column, 2) AS INT)) as MINS FROM table1
) AS TMP1
Where time_column is the column in the table and table1 is the name of the table. Example:
create table table1 (
time_column varchar(10)
);
insert into table1 (time_column) values ('12:20'), ('10:40'), ('15:50');
Results in: 38:50
Try this one -
Query:
DECLARE #temp TABLE
(
work_hour CHAR(5)
)
INSERT INTO #temp (work_hour)
VALUES
('10:24'),
('12:59'),
('06:28')
;WITH cte AS
(
SELECT mn = SUM(DATEDIFF(MINUTE, '19000101', CAST('19000101 ' + work_hour AS DATETIME)))
FROM #temp
)
SELECT CAST(FLOOR(mn / 60) AS VARCHAR(5)) + ':' + CAST(mn % 60 AS VARCHAR(2))
FROM cte
Output:
hm
--------
29:51
Update 2:
DECLARE #temp TABLE
(
transtime_out DATETIME
, transtime_in DATETIME
)
INSERT INTO #temp (transtime_out, transtime_in)
VALUES
('2013-05-19 16:40:53.000', '2013-05-19 08:58:07.000'),
('2013-05-19 16:40:53.000', '2013-05-19 08:58:07.000')
SELECT diff = LEFT(CONVERT(VARCHAR(10), CAST(SUM(CAST(a.transtime_out - a.transtime_in AS FLOAT)) AS DATETIME), 108), 5)
FROM #temp a

SUM minutes SQL server

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)