SQL - Subtracting Milliseconds from Current Date Time - sql

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())

Related

Storing Lap Times SQL Server

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

Subtracting two times to get duration

I am trying to subtract departure time from arrival time to get the duration of trips.
The arrival/departure is in the format of HH:MM.
I'm using postgresql, the time columns just say 'string' for how they are defined. A friend helped me cast them as integers, but I'm still stick at this point:
SELECT x, cast (table1.arrival as integer) - cast (table.1departure as integer), sum(y), count(*)
FROM table1 INNER JOIN table2
ON .....
GROUP BY .....
ORDER BY....
A friend told me this but I'm not totally sure what he means: "No you need to create a new variable for just minutes. 1:30 = 90 minutes. Cast that as integer then compute." How do I do this?
If the column is indeed a varchar (or text) then you need to first cast the column to a proper time.
SELECT x, table1.arrival::time - table.1departure::time, sum(y), count(*)
FROM table1 INNER JOIN table2
ON .....
GROUP BY .....
ORDER BY.
The above will fail if the time stored in the columns is not a properly formatted time in 24 hour format (e.g. 22:40)
The result of time - time is an interval. If you want to get the result in minutes, you need to extract them from the interval:
extract(epoch from table1.arrival::time - table.1departure::time) / 60
extract(epoch ..) returns the seconds in the interval that's why you need to divide it by 60 to get minutes.
This will however not work properly if the arrival and departure time are not on the same day (e.g. departure is at 23:25 and arrival is the next day at 07:23)
Unrelated but: you should never store dates, times or timestamps in varchar or text columns. Always use the proper data type.
If your RDBMS is Mysql you can use the MySQL DATEDIFF() Function
For example :
SELECT DATEDIFF(arrivale,departure) AS DiffDate
I assume here that the arrivale and the departure are in the same day.
And that arrivale and departue are TimeDate formated like HH:MM.

SQL - comparing date parameter to datetime

In a SQL Server table, I have a field named Timestamp, which is a 'datetime' field. On a screen I have created, a user will pass in a date (no time), and I need to return all the records for that date.
Just doing Timestamp = #Date doesn't seem to work unless the time in the field is 00:00:00. What is the most efficient way of doing this?
Since you're on SQL Server 2008, you can use the DATE datatype.
Do a comparison between
CAST(Timestamp AS DATE) = #Date
That should work and look just at the date - no time portion.
In general you should think about the data from a specific date as data that falls in a range, not at a single point in time. So ideally your query should use a range, such as:
WHERE [Timestamp] >= #Date
AND [Timestamp] < DATEADD(DAY, 1, #Date)
In this case, luckily, the optimizer is smart and will still use an index if you use CONVERT(DATE, [timestamp]) against the column. However in a lot of cases you need to be careful because this will often make your clause non-sargable.
PS Timestamp is a horrible column name. It's a data type in SQL Server which has nothing to do with date or time.
A common technique for truncating the time part off a datetime value is to use the DATEDIFF and DATEADD functions. In your example it would be used like this to truncate the time part of the Timestamp field.
WHERE #DateEntered = DATEADD(DAY,0, DATEDIFF(DAY, 0, Timestamp))
Bascially it's taking the datetime value and finding the name of days since "the date represented by 0" (for lack of a better description) and then adding that number of days back. This effectively truncates time part.

pgsql time diffrence?

How to write a query to find the time difference ?
time format is like this
2009-08-12 02:59:59
i want to compare
this time with
2009-08-12 02:59:10
how to check these two
i want to return some row having the time difference is 30sec
how to write a SQL statement ??
select date_part('second',date1) - date_part('second',date2)
In SQL you can do like this which give you output in seconds
SELECT * FROM your_table WHERE time1_column - time2_column = interval '30s'
Sorry this is the best I can do, given your description of the problem...
if both the times are columns in database table, you can directly use
relational operators (>, < and =)
Ex. if you have a table like
Test
(
id bigint,
starttime timestamp,
endtime timestamp
);
then you can have queries like
select * from test where starttime > end time
etc..
If you want to compare two dates in query, you can first convert text to time and then compare them
you can use: datetime function of pgsql
see: http://www.postgresql.org/docs/6.3/static/c10.htm
for more details

Convert SQL server datetime fields to compare date parts only, with indexed lookups

I've been doing a convert(varchar,datefield,112) on each date field that I'm using in 'between' queries in SQL server to ensure that I'm only accounting for dates and not missing any based on the time part of datetime fields.
Now, I'm hearing that the converts aren't indexable and that there are better methods, in SQL Server 2005, to compare the date part of datetimes in a query to determine if dates fall in a range.
What is the optimal, indexable, method of doing something like this:
select * from appointments
where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
The best way to strip the time portion of a datetime field is using datediff and dateadd functions.
DateAdd(day, datediff(day,0, MydateValue), 0)
This takes advantedge of the fact that SQL Server stores dates as two integers, one representing the number of days since day "0" - (1 jan 1900), and the second one which represents the number of ticks (each tick is about 3.33 ms) since midnight (for the time) *.
the formula above simply has to only read the first integer. There is no conversion or processing required, so it is extremely fast.
To make your queries use an index... use this formula on the input filtering parameters first, or on the "other" side of the equal sign from the tables date time field, so that the query optimizer does not have to run the calculation on every datetime field in the table to determine which rows satisfy the filter predicate. This makes your search argument "SARG-able" (Search ARGument)
Where MyDateTimeColumn > DateAdd(day,
datediff(day,0, #MydateParameter), 0) -- SARG-able
rather than
Where DateAdd(day, datediff(day,0,
MyDateTimeColumn ), 0) > #MydateParameter -- Not SARG-able
* NOTE. Internally, the second integer (the time part) stores ticks. In a day there are 24 x 60 X 60 X 300 = 25,920,000 ticks (serendipitously just below the max value a 32 bit integer can hold). However, you do not need to worry about this when arithmetically modifying a datetime... When adding or subtracting values from datetimes you can treat the value as a fraction as though it was exactly equal to the fractional portion of a day, as though the complete datetime value was a floating point number consisting of an integer portion representing the date and the fractional portion representing the time). i.e.,
`Declare #Dt DateTime Set #Dt = getdate()
Set #Dt = #Dt + 1.0/24 -- Adds one hour
Select #Dt
Set #Dt = #Dt - .25 -- Moves back 6 hours
Select #Dt`
Converting numeric types to string values (a type of Boxing) is not the best performing method of doing what you are looking for. Its not really about index-able, because the actual column type is date time.
If you are looking for the best way query for dates, then your example is right, but you may want to take into account the 3 ms precision difference in MSSQL. It can mean that records from one day can show up in another day's result.
This
select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
Should be this
select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<='08-14-2008 23:59:59.996'
It's correct - doing the conversion will execute the conversion for every row queried. It's better to leave the date columns as dates, and pass in your where clauses as dates:
select * from appointments where appointmentdate between
'08/01/2008' AND '08/16/2008'
Note: Leaving off the time means midnight (00:00.000), so you will include all times for 08/01, and all times from 08/15, and anything that is exactly 08/16/2008 00:00:00
Have a computed persisted column calculate the expression you need. If columns are computed and persisted, they can also be indexed.
There is also the way described at http://www.stillnetstudios.com/comparing-dates-without-times-in-sql-server/
SELECT CAST(FLOOR(CAST( getdate() AS float )) AS datetime)