I'm not a fan of working with dates in SQL Server and can never remember how to do some simple tasks off the top of my head.
One of them is truncating today's date.
convert(datetime, datediff(day, 0, getdate()))
I wanted to start creating wrapper functions for these for readability and reference.
create or alter function
/* Returns the date as of today at midnight (truncated)
*
* i.e.
* getdate() -> 2023-12-04 10:26
* date_today_midnight() -> 2023-12-04 00:00
*/
dbo.date_today_midnight()
returns
datetime
as begin
return convert(datetime, datediff(day, 0, getdate()));
end
Unfortunately there's a big performance hit when I swap my new function into the where clause.
select * from aTable where aDate >= convert(datetime, datediff(day, 0, getdate()));
-- runtime < 1s
select * from aTable where aDate >= date_today_midnight();
-- runtime > 10s
From my understanding, the problem is related to getdate() being a runtime constant function. So SQL server knows to swap that out with a constant at the beginning of query execution. Is there a way I can mark my own function as a runtime constant?
I tried using a CTE to get the date first, but that somehow resulted in even worse performance.
with dates as (select date_today_midnight() as today)
select * from aTable join dates on 1=1 where aDate >= dates.today;
-- runtime > 50s
Don't use the method you have, it hasn't been needed since SQL Server 2005. The
datedata type was added in SQL Server 2008 so there is no reason to use a "quirky" solution like you have here. if you want get the current date, as a date, then justCONVERT/CASTthe value to adate:As for using a function, again don't. User Defined Scalar functions are known to not be performant, as historically they weren't inlinable. In 2019+ (not what you are using) inlinable scalar functions were added. however, they have had also had performance issues, and the "solution" has often been for Microsoft add more and more requirements (caveats) to causing a function to be (not) inlinable. Using
GETDATE()in scalar function will cause it to not be inlinable:You could use an inline table value function, however, for something as trivial as this, there is entirely no need for such a function.
CONVERT/CASTthe value to adateis more than simple enough.If you were in SQL Server 2022+, you would also have access to the
DATETRUNCfunction:Unlike
CONVERT/CAST, this would retain the data type of the input expression, so would return2023-12-04T00:00:00.000rather than2023-12-04.