Calculate time difference in SQL - sql

We have two columns in SQL. one is total_work_time & next is total_exeption_time & both column data type is varchar
total_work_time value is 07:15:00
total_exeption_time value is 01:15:00
So I need to subtract total_work_time - total_exeption_time and the result will be 06:00:00.
I have tried with concat(DATEDIFF(HOUR,total_exeption_time,total_work_time),':', DATEDIFF(MINUTE,total_exeption_time,total_work_time))
But the result is 6:360. from this, 360 is the problem, it taken total minutes. I need the result structure like 06:00:00. How to fix this issue using SQL Server.

You should be storing time values in a TIME datatype - using the correct datatype is not only a best practice but will reduce the problems you face in future.
You can convert your VARCHAR values to TIME and then use the following calculation which takes the difference in seconds (your lowest unit of interest one assumes) and creates a new TIME result.
DECLARE #total_work_time TIME = '07:15:00', #total_exeption_time TIME = '01:15:00';
SELECT CONVERT(TIME, DATEADD(SECOND, DATEDIFF(SECOND, #total_exeption_time, #total_work_time), '00:00'));

Related

Convert to datetime in SQL Server

I have a simple SQL statement
select convert(datetime, '1/1/2018')
when I look at the output of it I see it is getting converted to 2018-01-01 00:00:00.000. Is it possible in the time section it gets the end of day time rather than the beginning of day?
I am using this to fetch data based on the converted date and it fails to retrieve this record 1/1/2018 15:10:43 because of the time thing.
Any suggestions?
Thanks
Update
Looks like I can do SELECT DATEADD(ms, -3, '5/31/2018') + 1 to solve my issue..Got the idea from Here
When I look at the output of it I see it is getting converted to
2018-01-31 00:00:00.000
I can't reproduce your result. select convert(datetime,'1/1/2018') doesn't return Jan 31st. It returns Jan 1st.
I am using this to fetch data based on the converted date and it fails
to retrieve this record 1/1/2018 15:10:43 because of the time thing
Since you are converting it to a DATETIME, it gets a time of 00:00:00 which is midnight. Thus, it fails to retrieve anything after midnight, like 15:10 on the same day. The easiest thing is to make your operator < the next day... so you don't have to account for hours, minutes, seconds, milliseconds...
where fetch < '20180102'
Notice I didn't use convert since SQL Server will handle that for us, but feel free to add it if it makes it clearer for you.
where fetch < convert(datetime,'20180102')
Also note that I used ANSI standars of YYYYMMDD. Other methods, which will cause issues when you use DATETIME2 or want a more precise measurement, is to add seconds to your date and use <=.
select dateadd(second,86399,convert(datetime,'20180101'))
Notice this has milliseconds of 000 though, so this can creep up on you later which is why I suggest using the next day.
For milliseconds...
select dateadd(millisecond,86399999,convert(datetime2,'20180101'))
If you are going to use a converted datetime to compare you need to be aware that it will always receive a time of 00:00:00.000. This will cause anything on that given date but with a greater time to be excluded from your results set.
To solve this issue you need to set the time on the field you are searching on to match. The code below will make every result in your datetime field have a time of 00:00:00.000, the same as your converted date.
(DATEADD(dd, DATEDIFF(dd, 0, my_col)

Subtract Two Date Time Values in SQL Server

I want to subtract two DateTime values:
I have Start DateTime #2015-06-14 23:00:00# End Date Time #2015-06-15 01:01:00#
I want to get the duration by time format like HH:MM:SS and update it in the duration column. I tried the following code but, it doesn't work.
update [ZainJTA].[dbo].[TBL_Justification]
set [Justification_Event_Duration]=CONVERT(Datetime,(DateDiff("n",[Justification_From],[Justification_TO])/60/24),108)
DATEDIFF returns an INT, so dividing it by two other INTs is going to give you - another INT, most likely zero.
Try:
CONVERT(Datetime,(DateDiff(s,[Justification_From],[Justification_TO])/60.0/60/24),108)
(the 60.0 will trigger conversion to a floating point format.)
However, it'd probably make more sense to store it as a number of seconds (integer), and only do the CONVERT when you output it to display.
To display as just the time, with no day/year part, you'll also need to do a second conversion:
CONVERT(VARCHAR, CONVERT(Datetime,
(DateDiff(s,[Justification_From],[Justification_TO])/60.0/60/24),108),108)

Get average of TIME(7)

ProcessTime: 00:00:00.0000012
RegexResolveTime: 00:00:00.0000421
MessageResolveTime: 00:00:00.0001269
FullProcessTime: 00:00:00.0001734
Ok, I've got 4 columns as above with datatype Time(7). I need to get the average of all the entries for those individual columns but Time(7) isn't a valid type for the AVG operator!
How does one go about getting the average of a Time(7) column?
I'll add that these are Timespans and not discrete points in time even though SQL server considers them such!
You can't average TIME because TIME represents a point in time, not a duration. I suggest one of two approaches.
The preferred approach: store duration as an integer in milliseconds, microseconds, nanoseconds, what have you. This will allow you much more precision if needed.
Apply conversions back and forth so you can average the delta from midnight instead of the actual time value.
DECLARE #x TABLE (ProcessTime TIME(7));
INSERT #x VALUES ('00:00:00.0000012'), ('00:00:00.0000016');
SELECT DATEADD(NANOSECOND, AVG(DATEDIFF(NANOSECOND, '00:00:00.0000000', ProcessTime)),
CONVERT(TIME, '00:00:00.0000000'))
FROM #x;
Results:
00:00:00.0000014
But doesn't that seem wrong to you? If you're not storing a point in time and you're only concerned about duration, store the duration. You can always format it as time when displaying.

SQL Calculations with HH:MM:SS

I have a column that comes into my SQL database as a varchar(10), but looks like HH:MM:SS. The column name is runTime.
I need to convert that column to seconds and do some calculations with it and another colunm called totalItems. totalItems is an int data type. An example of one calculation would be:
totalItems/runTime
So, it appears as though I need to convert runTime to a decimal, and then use it in the calculation, but when I can't do that without first converting the time to seconds, or I get an error (due to the ":").
So, how can I possibly convert the sessionRunTime into seconds first, and then convert those seconds to a decimal data type, then do the calculation from there? One example might be 59222 totalItems and 04:15:17 for runTime.
If there's a better way to handle this, I'm certainly open to that as well. Thanks!
So long as the hours portion doesn't match or exceed 24, you can convert to a datetime and use the built in functions to work out how long the time is in seconds:
select DATEDIFF(second,'00:00:00',CONVERT(datetime,'04:15:17'))
15317
If you need to do maths with this result, and the other value is an int, then multiple one or other of the values by 1.0 to force the maths to be done as floats, if that's required.
You can cast to datetime and use datediff to convert your string to seconds.
select datediff(second, 0, cast('04:15:17' as datetime))
Result:
15317

Storing "Time" in database- What to use DateTime/Interger/VarChar

I want to save Date and Time of the user on various activities performed. For date I have decided to use DateTime Column in Database and for Time I am in dilemma what datatype to go for.
I know in sql server 2008 Time datatype has been introduced but I am using older version i.e. Sql Server 2005 so I need your suggest to prove my understanding true or false.
I have seen people using varchar or DateTime for storing time into database. But I am looking towards usage of Integer datatype.
Reason for my selection is performance.
Following is the justification that I am giving to myself.
Assumptions
Any data saved into database must agree following rules
Date will be stored in format mm/dd/yyyy hh:MM:ss where hh:MM:ss will always be 00:00:00
Time will be stored in valid format (from hh:MM:ss as hhMMss)
if hh is 00
then MMss
and if MM is 00
then ss
and if ss is 00
then 0
hh will range in between 0-23
MM will range in between 0-59
ss will range in between 0-59
i.e. few examples
00:00:00 = 0
00:01:00 = 100
01:00:00 = 10000
13:00:00 = 130000
Personal thought why it will perform better.
SELECT * FROM Log WHERE loginDate = '05/23/2011'
AND loginTime BETWEEN 0 AND 235959 --Integer Comparison
When using JOINS on the basis of DateTime considering join for Date part only.
JOIN two tables on the basis of Common Dates irrespective of Time.I think Type Conversion would heavily impact in such cases if using DateTime as the storage datatype.
Since Sql will have to do an integer comparison and no typecasting would be required hence it should perform better.
EDIT
One drawback I just identified is when I want to get the difference between two times that how much time has been spent between 3 days, hopefully then it would become a nightmare to manage throughout the application.
So why do you need 2 columns. If the DateTime column (loginDate) has an empty time 00:00:00 why not just use that empty space for loginTime and have one column.
WHERE loginDate >= '05/23/2011' AND loginDate < '05/24/2011'
If you're intent on using an integer, there's nothing wrong with it.
Bearing your edit in mind, your ideal solution is to put both date and time in the same column, a DATETIME:
You can then trivially figure the difference between start and end times with DATEDIFF
You can easily establish just the date portion with CONVERT(varchar(10), loginDate, 101)
You can easily establish just the time portion with CONVERT(varchar(10), loginDate, 108)
Storage issues might be resolved by using SMALLDATETIME, if precision < 1minute isn't required. SMALLDATETIME requires four bytes per column, which is the same as INTEGER, so you're making a significant net gain over using two columns.