Unexpected results when subtracting milliseconds in SQL [duplicate] - sql

This question already has answers here:
DateTime2 vs DateTime in SQL Server
(17 answers)
Closed 3 years ago.
I'm trying to do some DateTime logic in SQL:
SET #DayEnd = DATEADD(MILLISECOND, -1, #BeginNextDay)
If, for instance, #BeginNextDay is '2019-02-04 00:00:00.000' and I'm performing the code above, I would expect #DayEnd to be '2019-02-03 29:59:59:999'. Unfortunately this isn't the case, the result is '2019-02-04 00:00:00.000'.
When I'm subtracting 12 milliseconds, the result is '2019-02-03 23:59:59.987'.
When I'm substracting 10 milliseconds, the result is '2019-02-03 23:59:59.990' as expected.
Can somebody explain to me what SQL is doing that gives me this (for me) unexpected result?

Don't do it! Just use:
SET #DayEnd = #BeginNextDay; -- if you even need this
And change your logic to be:
WHERE datecol < #DayEnd
rather than:
WHERE datecol <= #DayEnd -- or equivalently using BETWEEN
Don't fiddle with milliseconds to define time periods. Use >= and < to define the period.

Related

Find rows that have yesterdays date -- Invalid column? [duplicate]

This question already has answers here:
How to use alias column name in where clause in SQL Server
(5 answers)
Using new columns in the "where" clause
(5 answers)
Closed 20 days ago.
Goal: I am trying to get the rows in a table that have yesterdays date (but the original column is in datetime).
What I've tried:
I was able to figure out how to get yesterdays date from https://learnsql.com/cookbook/how-to-get-yesterdays-date-in-t-sql/
But I also had to cast the DateTime from the table to date to match that yesterdays date was in Date format. So the SO articles like SQL statement to select all rows from previous day did not work.
When I try to find the matching rows from my DB Table, it says:
Invalid column name 'YesterdayDate'
SQL:
SELECT cast(DateEnded as date) AS YesterdayDate
FROM [dbo].[V]
WHERE YesterdayDate = DATEADD(DAY, -1, CAST(GETDATE() AS date));
How can I correctly do this?
In fact don't do it that way. You want to avoid calling functions on columns in your WHERE clause as they can make the query unsargable i.e. unable to use indexes. Instead use the actual column, and rather than converting to a date use a datetime window of the previous day.
SELECT CAST(DateEnded AS date) AS YesterdayDate
FROM [dbo].[V]
WHERE DateEnded >= DATEADD(DAY, -1, CAST(GETDATE() AS date))
AND DateEnded < CAST(GETDATE() AS date);

Query data from previous day when month/year changes

In a SQL Server query, I am currently using the clause
WHERE
DAY(trade_date) = DAY(GETDATE()) - 1
AND MONTH(trade_date) = MONTH(GETDATE())
AND YEAR(trade_date) = YEAR(GETDATE())
to query my data from the previous day.
It is working fine right now but my question is if, for example, on 8/1/2021, SQL Server will try to get data from 8/0/2021 or if it will know to get data from 7/31/2021.
If this query won't work what could I use instead? Thanks!
I would recommend using proper date comparison logic - instead of breaking it down to day, month and year. Also, it is recommended to use proper date arithmetic functions like DATEADD instead of just - 1 on your date values (never sure what that -1 stands for: minus one day? Week? Month? Hour?).
And lastly - I would also recommend using SYSDATETIME() instead of GETDATE() since the latter always returns a DATETIME datatype - which should be on its way out, and you should use DATE (if you don't need to time portion), or DATETIME2(n) (if you do need the time portion) since those are more efficient and have fewer limitations compared to DATETIME.
If your trade_date is a DATE column (as it probably should be), just use:
WHERE
trade_date = DATEADD(DAY, -1, SYSDATETIME())
and if it's not a DATE - just cast it to a date as needed:
WHERE
CAST(trade_date AS DATE) = DATEADD(DAY, -1, CAST(SYSDATETIME() AS DATE))

Set datetime with random trailing nanoseconds to zero's [duplicate]

This question already has answers here:
Truncate Datetime to Second (Remove Milliseconds) in T-SQL
(9 answers)
Closed 5 years ago.
I have multiple dates in a table with the following date format, example:
2016-01-03 12:04:00.0123123
I need to update the entire table to update all the trailing mili and nanoseconds to zero's
So the above date should become:
2016-01-03 12:04:00.0000000
is there anyone that can assist me with this update script?
thx in advance
I think decoding and encoding the values while ommiting the milliseconds should do the trick:
UPDATE table
SET field = DATETIMEFROMPARTS(
DATEPART(year, field),
DATEPART(month, field),
DATEPART(day, field),
DATEPART(hour, field),
DATEPART(minute, field),
DATEPART(second, field),
0);
The decoding is done with DATEPART(). For the encoding DATETIMEFROMPARTS() is used.
If your field is of type DATETIME2 you would use DATETIME2FROMPARTS().

How to cast GETDATE() to be only time ignore day,month and year [duplicate]

This question already has answers here:
Compare time part of DateTime data type in SQL Server 2005
(6 answers)
Closed 4 years ago.
I have a table for store takt-time. It's compound with "day_shift(1)" and "night_shift(0)" like below.
If I put current time(by using GETDATE() function ).
I need to know this current time is "day(1)" or "night(0)". my query like this.
SELECT [day_shift_flag]
FROM [company_working_time]
WHERE GETDATE() BETWEEN [start_time] AND[end_time]
But it can't found because a date received from GETDATE() isn't '1900-01-01'
How to compare a only time and ignore day,month,year.
What should I do?
You can cast a DateTime as a Time data type. For example:
SELECT
[day_shift_flag]
FROM [company_working_time]
WHERE
CAST(GETDATE() AS TIME) BETWEEN CAST([start_time] AS TIME) AND CAST([end_time] AS TIME)
By Following Way You can Ignore the day,month,year
SELECT [day_shift_flag]
FROM [company_working_time]
WHERE DatePart(HH,GETDATE()) BETWEEN DatePart(HH,[start_time]) AND DatePart(HH,[end_time])

query to select data from this day [duplicate]

This question already has answers here:
In SQL Server, what is the best way to filter items for an entire day
(3 answers)
Closed 8 years ago.
I have a database table that has Datelogged columns from type Datetime (Sql server 2008 r2)
The Datelogged value is like this 2014-10-22 12:57:36.583
I want to do a query to select all the rows that its date is today (I care about year, month, and day) but not (hour, second.)
This is my query
string query = "SELECT * FROM Orders WHERE PrintTime is NULL WHERE Datelogged = #Datelogged";
but I didn't know what should I do to tell the query to compare just on year-month-day
Based on #Aaron Bertrand comment
It appears that it is better to use a Date Range from current day midnight (00:00:00) to < tomorrow at midnight.
Query copied from his comment.
DateLogged >= CONVERT(DATE, #DateLogged) AND
DateLogged < DATEADD(DAY, 1, CONVERT(DATE, #DateLogged))
Also see: Bad habits to kick : mis-handling date / range queries By Aaron Bertrand
(Old Answer)
You can use CONVERT(DATE, Datelogged) to get Date part without time.
"SELECT * FROM Orders WHERE PrintTime is NULL AND CONVERT(DATE, Datelogged) = #Datelogged"
Make sure you pass the parameter value using Date property in C# like:
cmd.Paramaters.AddWithValue("#Datelogged", DateTime.Today);// or DateTime.Now.Date
Also make sure to remove multiple WHERE from your query and use AND or OR to combine two conditions depending on your requirement.
Get the minimum date time range for current date and maximum date time range for today. Then, compare it with the logged date value.
Conversion operator on any table column adds extra conversion overhead and leads to inefficient use of index. Should be avoided when possible.
SELECT * FROM Orders
WHERE PrintTime is NULL
AND (Datelogged > dateadd(DD, -1, cast( GETDATE() as date)) AND Datelogged < dateadd(DD, 1, cast( GETDATE() as date)));