2016-04-05 14 views
-4

Почему это дает мне результат как DATETIME?Что за трюк за этим кодом?

Select DATEADD(yy,116, 0) 

Выход:

2016-01-01 00:00:00.000 

и это

Select DATEADD(yy,116 +1, -1) 

Возвращает меня в последний день года?

Какая уловка за этим? Я просто играл с ним, но не понимаю, как это получилось?

+0

Какую часть вы не понимаете, точно? Не могли бы вы подробнее рассказать об этом? –

ответ

4

Порка мертвую лошадь на этом, но вот мое объяснение.

DATEADD(yy... добавляет годы к указанной дате. (В стороне, сокращенные формы злы, вы должны использовать DATEADD(YEAR,...) для ясности).

Дата 0, как и все остальные, Полночь, понедельник, 1 января 1900 года. Дата -1 - воскресенье, 31 декабря 1899 года, за 1 день до этого.

Если добавить 116+1 к дате -1 Вы получаете 31 декабря, (1899 + 117) = 2016. Вы также можете написать это как SELECT DATEADD(YEAR,117, '1899-12-31') или множество других способов с использованием даты литералов.

Bonus

Как почему он возвращает Datetime в противоположность Datetime2, а Smalldatetime или любой другой тип, DATEADD возвращает любой тип вы передаете в качестве параметра даты. -1 преобразуется неявно (согласно нормальным правилам литья/конвертации) в Datetime - см. https://msdn.microsoft.com/en-AU/library/ms187928.aspx.

Если вы хотите увидеть это в действии, этот код покажет вам результат кормления DATEADD с различными типами:

SELECT 
    SQL_VARIANT_PROPERTY(GETDATE(), 'BaseType') BaseType, 
    SQL_VARIANT_PROPERTY(DATEADD(DAY, 1, GETDATE()), 'BaseType') DateAddBaseType, 
    SQL_VARIANT_PROPERTY(DATEADD(DAY, 1, CAST(GETDATE() AS DATETIME2)), 'BaseType') DateAddDatetime2, 
    SQL_VARIANT_PROPERTY(DATEADD(DAY, 1, CAST(GETDATE() AS SMALLDATETIME)), 'BaseType') DateAddSmallDatetime, 
    SQL_VARIANT_PROPERTY(DATEADD(DAY, 1, CONVERT(DATETIME2, GETDATE())), 'BaseType') DateAddDatetime2Convert 

Extra Bonus

Если вы хотите, последний день текущий год:

SELECT DATEADD(DAY, -1, DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE())+1,0)) 

Или если вы хотите получить последнее разрешимое datetime2 текущего года (то есть 100 нс для е полночь день нового года):

SELECT DATEADD(NANOSECOND, -100,CAST(DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE())+1,0) AS DATETIME2(7))) 

Изучение каждого из них, и, надеюсь, вы будете иметь возможность работать, что они делают.

+0

Возможно, вы порка мертвой лошади, но ваш ответ является самым полным. Я думаю, это может быть слишком много для этого вопроса, но вы все равно получили мой голос. –

+0

@zohar спасибо! Мне очень нравится вопрос на дате :) –

5

Дата 0 является 1900-01-01,

Так Дата -1 является 1899-12-31 т.е. (разбавить 1 день от 1900-01-01)

SELECT CONVERT(datetime, 0) : Result is 1900-01-01 00:00:00.000 

Так Select DATEADD(yy,116 +1, -1) добавит 116 + 1 (т.е. 117) году до 1899

(117 years will add to 1899-12-31 00:00:00.000)

+0

спасибо, бха, но не очень ясно мне – Stacky

+0

какая часть, что тебе непонятно? – Squirrel

3

SQL Server datetimes основаны на количестве дней с 1900-01-01.

0 = 1900-01-01 
-1 = 1899-12-31 

Теперь вы добавляете 116 лет к # 1, и вы добавляете 117 лет к # 2.

+0

благодарит за ответ, но не ясно мне sir – Stacky

0

Sql-сервер хранит значения datetime как 8 байт - первые 4 байта представляют количество дней с 1 января 1900 года, а последние 4 байта представляют количество тиков с полуночи (галочка составляет 3,3 миллисекунды, поэтому datetime предел точности составляет 3,3 мс).

Итак, при преобразовании 0 в значение datetime вы получаете 1900-01-01.
при конвертации 1 вы получаете 1900-01-02,
и при конвертации -1 вы получаете 1899-12-31.

так, простая математика - добавление от 116 лет до 1900 даст 2016.
добавление 117 лет к 1899-12-31 приведет к 2016-12-31 годам.

Для получения дополнительной информации о хранении даты и времени в SQL-сервере вы можете прочитать this article.

Смежные вопросы