The problem is that in the ISNULL we have a datetime2 (the field man_stop) and getdate as fallback (returns a datetime) and apprently the ISNULL cast the second param based on the first param....Consequently, we are comparing the getdate() as datetime with a getdate() as datetime2.
Note that the man_stop (end of the customer mandate) is most of the time not null as the mandate are running.
Then, you must take a look at this article and specifically about the sentence :
As for the time portion, SQL Server starts with 0 and increments the numeric value for each .003 seconds after midnight.
Means what ? if the time is 12:15:00:002 is actually stored as 12:15:00:003 but compared with 12:15:00.002 so not equal !!
SOLUTION 1
So, to fix the problem for SQL Server 2017 (no problem with SQL Server 2014 though), I simply converted my fields datetime2 to datetime to have a correct comparison with getdate() as datetime :
[isActive] AS (case when getdate()>=isnull(CONVERT([datetime],[man_start]),getdate()) AND getdate()<=isnull(dateadd(day,(1),CONVERT([datetime],[man_stop])),getdate()) then (1) else (0) end)
SOLUTION 2
Or I could also convert all the datetime to datetime2. Instead of GETDATE() use SYSDATETIME() returning a datetime2(7). As my two fields are simply datetime2 (no precision defined) the comparison was worse...but when converting the datetime2 to datetime2(7) it was running like a charm. So it becomes :
(case when SYSDATETIME () >= isnull(convert(datetime2(7), [man_start]),SYSDATETIME()) AND SYSDATETIME() <= isnull(dateadd(day,(1),convert(datetime2(7), [man_stop])),SYSDATETIME()) then (1) else (0) end)
SOLUTION 3
Change the database compatibility level to 120 or lower to preserve the legacy behavior when comparing datetime and datetime 2 types. This breaking change was introduced in SQL Server 2016.
SOLUTION 4 (solution applied)
Use same type of data and avoid type conversion.
Change the type of the fields man_start
and man_stop
as datetime2(7) (instead of datetime2 which is datetime2(3)) to match SYSDATETIME() function returned type (datetime2(7)).
ALTER TABLE myTable ALTER COLUMN [man_start] datetime2(7) NULL
ALTER TABLE myTable ALTER COLUMN [man_stop] datetime2(7) NULL
So my computed column becomes :
[isActive] AS (CASE WHEN SYSDATETIME() >= ISNULL([man_start],SYSDATETIME()) AND SYSDATETIME() <= isnull(dateadd(day,(1),[man_stop]),SYSDATETIME()) THEN 1 ELSE 0 END)
Advantages : Compatibility level remains, avoid type conversion (better peformance)