SQL Calculations with HH:MM:SS - sql-server-2005

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

Related

What do I have to change in my syntax for it to work in MS SQL Server from Informix

I'm currently updating a lot of our queries to work again in our new ERP-Release, where we will be working with MS SQL Server, swapping away from our current Informix database. Many are just simple Date-Format changes but this one I am unable to translate.
It really only is the following line:
round((GETDATE() - max(l105.dataen))::interval second(9) to second::char(10)::int
/ 60 / 60, 3)
I simply can't grasp what the part starting at the colons (::) is doing or what function it is.
I hope someone maybe can identify it.
In Informix, subtracting two DATETIME values results in an INTERVAL. The <value>::<type> notation is a shorthand for CAST(<value> AS <type>). Therefore, there are three consecutive casts:
::interval second(9) to second
::char(10)
::int
By default, if you subtract two DATETIME YEAR TO SECOND values, you will get an INTERVAL DAY(n) TO SECOND value. The first cast converts that to INTERVAL SECOND(9) TO SECOND — a number of seconds; the second cast converts the result to CHAR(10) because there isn't a direct conversion from INTERVAL to numeric types; the third cast converts the string to an INT. That gives the integer number of seconds; it is divided by 60 twice (effectively, divided by 3600) to convert the seconds into hours.
The result is then rounded to 3 decimal places.
So, the overall operation calculates the number of hours between two times.
The two times are the current time and the most recent value in the l105.dataen column (the MAX expression). Presumably, there is a GROUP BY clause somewhere in the SELECT statement that this is a part of.
You will likely need to use a 'time difference' function in MS SQL Server, and maybe the function allows you to control the presentation of the result as a number of hours and fractions of an hour.
Judging from DATEDIFF function, you will need to use something like:
DATEDIFF(hh, MAX(l105.dataen), GETDATE())
However, that returns an integer value for the difference in hours. You may prefer to get the time in seconds and divide by 3600 to get a fractional value:
DATEDIFF(ss, MAX(l105.dataen), GETDATE()) / 3600.0
No database server was consulted to ensure the veracity of the suggested translation.

SQL-Server Time data type

From what i've read so far, the data type time in sql server (starting with 2008) should be able to store the time in a HH:MM format. Then I tried this myself with the following simple exercise:
create table #mytable (id int, lat float, lon float, trajectory_id int, theTime time(5))
insert into #mytable values
('1','15.8','17.1','162','10:01'),
('2','11.5','59.7','162','10:02'),
('3','16.4','79.9','162','10:03'),
('4','29.5','10.3','180','11:12'),
('5','58.2','11.1','180','11:13'),
('6','54.5','14.1','180','11:14'),
('7','14.9','15.2','166','13:40'),
('8','15.0','13.1','166','13:42')
My expected result for the column theTime was:
theTime
10:01
10:02
10:03
11:12
11:13
11:14
13:40
13:42
What I got instead was:
theTime
10:01:00.00000
10:02:00.00000
10:03:00.00000
11:12:00.00000
11:13:00.00000
11:14:00.00000
13:40:00.00000
13:42:00.00000
Sure, I could select left(theTime, 5) and get the expected result. But i'm wondering how I could insert it directly in the desired format.
I want to use a built in function and not to store the numbers in an int for HH, MM, SS as one might have used before sql server 2005.
Using sql server 2012. Thanks
You seem confused by the difference between internal formats and display formats. TIME is a data type built into the language. When it prints out, it prints out with hours, minutes, and seconds. That is how the data type prints out, in the same way the SQL Server does not put commas in integers bigger than 1000 and uses an appropriate symbol for the decimal place. (Or for that matter prints out integers in base 10 rather than the binary format as they are actually stored.)
When you say TIME(5) you are saying that you want at least 5 decimal places of precision for fractional seconds: HH:MM:SS.SSSSS. There is no option for removing seconds altogether from the time type.
If you want to print it out in a particular format, use convert(), cast(), or format(). Happily, cast() works quite well for times. The plethora of inscrutable numeric codes for date/time are more applicable to dates, than times.
When you do left(thetime, 5) then you are implicitly converting time to a string and taking the first five characters. This seems to meet your needs. I would suggest that you just build this into your table:
alter table #mytable add thetime_hhmm as (left(thetime, 5));
Then you can use thetime_hhmm to get the value as a string with the format you want.
You can't control the format that a data type is stored as. Your time data is actually being stored as a bunch of bits -- 0's and 1's -- and it's only being displayed like 10:01:00.00000 in your query analyzer.
If you want to show it in another format, then you have to convert it to a text data type like varchar, but this is usually something your UI layer should handle, not your data layer.

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)

Convert time from seconds to hours, with rounding

I need to convert time from seconds to hours with 2 decimal rounding
PeriodLength contains time in seconds.
(c.PeriodLength)/3600. as Time
Returns time in hours but result is like 1.250000
and I need it to be 1.25.
Using standard SQL, you can convert it to a decimal. Something like:
select cast(c.PeriodLength / (60.00*60) as decimal(6, 2));
There are also database specific solutions, but you don't specify the database.
SET value = ROUND(value,2)
Note that this is generally used for statistical purposes, rather than monetary or time. However, it should work for what you are seeking.

Like operator in Datetime column

I want to use Like operator in a column of datetime. The values of the column is as follows:
2013-08-31 17:54:52.000
2013-08-31 17:54:52.000
My query is as below:
SELECT * FROM table where created_date Like '%54%'
It works fine. but when I search for '%52%' instead of '%54%', it gives me nothing. (It is working when I search till the minutes, but when I search for seconds or milli seconds it does not work.)
I have looked at the following url and it is working
SQL LIKE Statement on a DateTime Type
I want to know the reason, why this is happening and how like operator works with datetime type column.
I think it would be a better idea to use the DATEPART operator of SQL SERVER to extract the portion of date.
And example could be like:-
SELECT * FROM table
where DATEPART(minute,created_date)=54
EDIT:-
I want to know the reason, why this is happening and how like operator
works with datetime type column.
Actually there is no direct support given by SQL Server for LIKE operator for DATETIME variable but you can always cast the DATETIME to a VARCHAR and then try to use the LIKE operator as you want.
On a side note:-
MSDN says:-
DATEPART can be used in the select list, WHERE, HAVING, GROUP BY and
ORDER BY clauses.
In SQL Server 2012, DATEPART implicitly casts string literals as a
datetime2 type. This means that DATEPART does not support the format
YDM when the date is passed as a string. You must explicitly cast the
string to a datetime or smalldatetime type to use the YDM format.
The 'LIKE' operator and any regular expression operators provided by other databases are used to process text values. A date is definitely not a text value, it is a separata type by itself.
It makes little sense to apply a text operator to a non-text type (like int or DATETIME or DATETIMEOFFSET), which is why you can't use LIKE on dates in any database. First of all, the values are not stored as text but in an implementation-specific binary form.
Then, while you can use LIKE on a specific text representation of a date, eg using CAST you have to absolutely certain what that representation is. Different locales display dates differently, with year first, year last, month first or last or whatever. What would you search against?
Moreover, what is 54? 54 minutes, 54 seconds or 654 milliseconds?
The only sensible solution is to use DATEPART to check specific parts of a date, or the BETWEEN operator to check for ranges.