Storing Lap Times SQL Server - sql

Whats the best solution to store lap times on a SQL-Server database? the suggested format should be 01:52.525. I'm using time(3) but it does not allow me to use the Avg() Function.
Best regards,

Since you are already storing the lap duration as time, you can use DATEDIFF to calculate duration in milliseconds for the average calc and use DATEADD to convert milliseconds to time.
SELECT
AVG(DATEDIFF(millisecond, '', LapTime)) AS AvgLapTimeMilliseconds
, CAST(DATEADD(millisecond, AVG(DATEDIFF(millisecond, '', LapTime)), '') AS time(3)) AS AvgLapTime
FROM dbo.Lap;

Try storing the start time and duration (lap time) in epoch milliseconds, then use a SQL query (which would allow Avg()):
SELECT (duration - start) FROM lap_times (WHERE ...)
Refer to this answer for converting milliseconds to a human-readable timestamp.

Store the times as time. Add computed columns with the values as milliseconds. Use the computed columns for calculations.
For example:
alter table t add laptime_ms as (datediff(ms, 0, laptime));
You can now use this for averages, and convert back to time as:
select convert(time, dateadd(ms, 0, avg(laptime_ms)))
from t

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.

Calculate time difference in 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'));

SQL - Subtracting Milliseconds from Current Date Time

I am trying to write a query that will let me get records entered between now and a some number of minutes in the past. I have the number of minutes as milliseconds. So, I'm trying to write a SQL query that will let me get those records.
I see a DateAdd function. However, I don't see a function to Subtract some time from a date. From a pseduo-code perspective, I'm trying to do this:
SELECT
*
FROM
MyTable
WHERE
CreatedAt > (GetUtcDate() - milliseconds)
How do I get records from MyTable that have happened within some past window of time?
We can try using DATEADD in millisecond mode:
SELECT *
FROM MyTable
WHERE CreatedAt > DATEADD(ms, -60000, GETDATE()); -- 60000 ms = 1 minute
This would return all records which were created within one minute of the current date and time.
The function you want is DATEADD (Transact-SQL).
SELECT {YourColumns}
FROM MyTable MT
WHERE CreatedAt > DATEADD(millisecond,{value},GETUTCDATE());
Despite its name, the DATEADD function is also the "DATESUBTRACT" function that you're looking for. (Intentionally double-quoted as quasi-code.)
The first parameter defines the sorts of units you're adding or subtracting, i.e. HOUR, DAY, WEEK, etc., or, in your case, MILLISECOND. In the second parameter, if you want to add time, you enter a positive number. If you want to subtract time, as you do here, enter a negative number of units.
The best way to interact with date and time in SQL is to use specific date and time functions rather than adding dates as you would add numbers.
In this case the function you are looking for is DATEADD, using it your cord should change like this:
SELECT *
FROM MyTable
WHERE CreatedAt > DATEADD(ms, -milliseconds, GetUtcDate())

How to cast the DateTime to Time

I am casting DateTime field to Time by using CAST Syntax.
select CAST([time] as time) as [CSTTime]
DateTime
2015-03-19 00:00:00.000
Present Output : Time
03:05:36.0000000
I need only HH:MM:SS and not Milliseconds or 0000's
How to filter or Cast it to exact HH:MM:SS Format.
Time is not stored with its display format in SQL Server.
Therefore, from the user perspective, you can say that it has no format.
Of course, that's not completely accurate since it does have a storage format, but as an average user you can't really use it.
This is true for all date and time data types:
Date, DateTimeOffset, DateTime2, SmallDateTime, DateTime and Time.
If you need a format then you don't need to cast to time but to a char. Use Convert to get the char you need:
SELECT CONVERT(char(10), [time], 108) as CSTTime
Here is some background data if you're interested:
In this article published in 2000 the writer explains in depth how SQL Server treats dates and times. I doubt if anything significant changed between 2000 and 2015 in the way SQL Server stores date, time and datetime values internally.
Here are the relevant quotes, if you don't want to read all of it:
So how does SQL Server internally store the dates? It uses 8 bytes to store a datetime value—the first 4 for the date and the second 4 for the time. SQL Server can interpret both sets of 4 bytes as integers.
........
........
SQL Server stores the second integer for the time as the number of clock ticks after midnight. A second contains 300 ticks, so a tick equals 3.3 milliseconds (ms).
since time is actually stored as a 4 byte integer, it really doesn't have a format as an integral part of the data type.
You might also want to check out this article for a more detailed explanation with code samples.
You can achieve it with CAST just simple use TIME(0) datatype in following:
SELECT CAST('2015-03-19 01:05:06.289' AS TIME(0))
OUTPUT:
01:05:06
SQL Server 2008:
select cast(MyDate as time) [time] from yourtable
Earlier versions:
select convert(char(5), MyDate , 108) [time] from yourtable
Other Options:
SELECT CONVERT(VARCHAR(20), GETDATE(), 114)
The simplest way to get the time from datetime without millisecond stack is:
SELECT CONVERT(time(0),GETDATE())
Hour and Minute
SELECT substring(CONVERT(VARCHAR, GETDATE(), 108),0,6) AS Time

SELECT average timestamp difference in JPA with Postgres and HSQL

I have a table with two timestamp columns, startTime and stopTime, and I would like to calculate the average difference of these timestamps in my table. I have a solution that works in Postgres and in HSQLDB (which I use for local unit testing) but not both, and I'm having trouble trying to figure out a common solution.
Postgres:
select EXTRACT(EPOCH FROM(avg(m.stopTime - m.startTime))) from Measures m
HSQL:
select avg(FUNC('UNIX_TIMESTAMP', m.stopTime) - FUNC('UNIX_TIMESTAMP', m.startTime) from Measures m
Is there a way to use the same query for both databases? All of the functions I've found seem to only be supported in one database or the other.
I think my main problem is that there isn't a common function to convert a timestamp to seconds in order to perform the calculation. EPOCH is only compatible with Postgres and UNIX_TIMESTAMP is only compatible with HSQL.
The crux of your problem is converting the dates and timestamps down to a number of seconds. Instead of using epoch, I'll use a julian date for the date. I'll convert the julian date to seconds, then add the number of seconds since minight for each timestamp being compared. The following query does not calculate the difference, it simply converts the date to a number that's similar on both platforms .. you'll have to do this once for each date being compared. note: replace "current"timestamp" with m.startTime and m.stopTime respectively.
select
(to_number(to_char(current_timestamp,'J'),'99999999999999999999')*86400/*convert from julian days to julian seconds*/)
+ (to_number(to_char(current_timestamp,'HH'),'99') * 3600) /*Hours to seconds */
+ (to_number(to_char(current_timestamp,'MM'),'99') * 60) /*Minutes to seconds */
+ (to_number(to_char(current_timestamp,'SS'),'99') /*add in the seconds*/
Ugly as sin, I know-- perhaps you can rewrite it easier as function, but as I don't know hsqls full feature set, I'll leave it in this form rather than using a CTE or function.