I am trying to get Datediff
between GETDATE()
and SYSDATETIME()
in milliseconds.
SELECT DATEDIFF(ms, GETDATE() , SYSDATETIME());
The result I am getting is 0
or 1
or 2
or 3
. What is the reason for this difference?
See this fiddle.
They are two different function calls that can return two different times.
Additionally GETDATE
returns a datetime
datatype which only has precision of 3-4 ms whereas SYSDATETIME()
returns a datetime2(7)
datatype.
Even if both calls were to return exactly the same time you could see the issue that you are experiencing due to rounding.
DECLARE @D1 DATETIME2 = '2012-08-18 10:08:40.0650000'
DECLARE @D2 DATETIME = @D1 /*Rounded to 2012-08-18 10:08:40.067*/
SELECT DATEDIFF(ms, @D1 , @D2) /*Returns 2*/
The other answer is incorrect that if you substitute in GETDATE()
the function is only called once as can be demonstrated from the below.
WHILE DATEDIFF(ms, GETDATE() , GETDATE()) = 0
PRINT 'This will not run in an infinite loop'
When running a loop on my windows XP desktop with GETDATE()
and SYSDATETIME
I can also see results that indicate that something else might be going on as well though. Perhaps calling a different API.
CREATE TABLE #DT2
(
[D1] [DATETIME2](7),
[D2] [DATETIME2](7)
)
GO
INSERT INTO #DT2
VALUES(Getdate(), Sysdatetime())
GO 100
SELECT DISTINCT [D1],
[D2],
Datediff(MS, [D1], [D2]) AS MS
FROM #DT2
DROP TABLE #DT2
Example results below
+-----------------------------+-----------------------------+-----+
| D1 | D2 | MS |
+-----------------------------+-----------------------------+-----+
| 2012-08-18 10:16:03.2500000 | 2012-08-18 10:16:03.2501680 | 0 |
| 2012-08-18 10:16:03.2530000 | 2012-08-18 10:16:03.2501680 | -3 |
| 2012-08-18 10:16:03.2570000 | 2012-08-18 10:16:03.2501680 | -7 |
| 2012-08-18 10:16:03.2600000 | 2012-08-18 10:16:03.2501680 | -10 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2501680 | -13 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2657914 | 2 |
| 2012-08-18 10:16:03.2670000 | 2012-08-18 10:16:03.2657914 | -2 |
| 2012-08-18 10:16:03.2700000 | 2012-08-18 10:16:03.2657914 | -5 |
| 2012-08-18 10:16:03.2730000 | 2012-08-18 10:16:03.2657914 | -8 |
| 2012-08-18 10:16:03.2770000 | 2012-08-18 10:16:03.2657914 | -12 |
| 2012-08-18 10:16:03.2800000 | 2012-08-18 10:16:03.2814148 | 1 |
+-----------------------------+-----------------------------+-----+
The rows of interest are
| 2012-08-18 10:16:03.2600000 | 2012-08-18 10:16:03.2501680 | -10 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2501680 | -13 |
This discrepancy is too large to be a rounding issue and can't just be a timing issue with a delay between calling the two functions as the issue exists on more than one row that GETDATE
reports 10:16:03.26X
whereas SYSDATETIME
reports 10:16:03.250
They differ because the two functions can't be called simultaneously (at the exact same time). Other processes running can affect the timings. There are dozens of reasons they can differ by varying amounts.
If you do the same thing with two calls to GetDate()
instead, they result in no difference, because the database engine is smart enough to figure out they're the same thing and re-use the results. Using GetDate()
and SysDateTime()
is different, though, because they're not the same code path (they do different things).
Think of it this way: If you see 1 + 2
and 1 + 2
, it's easy to see that the first expression and the second are the same, and so you only have to do the calculation once. If you change it to 1 + Rand()
and 1 + Rand()
, you have no way of knowing what the two different calls to Rand()
will return, so you have to do the calculations separately.
This difference is a good example of the difference between PRECISION and RESOLUTION (let's leave ACCURACY to one side for the moment).
GETDATE() returns a DATETIME with (apparently) a PRECISION to the millisecond, but, if you put it in a tight loop, you'll find the next different value returned is several milliseconds later; it can only return about 300 different values each second, as its RESOLUTION is only to about 3 or 4 milliseconds. read more about this here This is a design feature/compromise of the DATETIME datatype.