Вы неправильно понимаете, как значения даты работают в базе данных. Нет читаемого человеком формата .Когда вы видите DateTime
или DateTime2
значения, отформатированные как yyyy-mm-dd
, то для удобства вы видите что-то, показанное вашим отладчиком или инструментом запросов;фактическое значение, используемое в базе данных, является двоичным, не читаемым человеком и должно быть эффективным для хранения, индексации и арифметики даты.
Если вам нужно увидеть значение в определенном формате, вы должны convert()
или format()
это тип в семействе varchar
как часть запроса.Или, что еще лучше, пусть ваш код приложения / инструмент отчетности сделает это за вас и просто вернет исходное значение.
Я также вижу указание, что эти даты потенциально сохраняются в varchar
или nvarchar
столбец.Если это так, это главный недостаток в дизайне схемы. Вы получите значительные преимущества в производительности и избавите себя от больших головных болей в будущем, если сможете начать хранить эти значения с помощью типаПрежде всего, из семейства DateTime
.
Имея это в виду и поскольку неясно, с чего вы начинаете, давайте рассмотрим пять сценариев в порядке предпочтения:
В столбце уже используется тип из семейства DateTime
, и вы можете позволить своему приложению / инструменту отчетности обрабатывать формат
Хорошо, если вы используете реальное значение DateTime в схеме.Это то, что мы ожидаем увидеть.Более того, внезапно все становится на действительно простым в вашем SQL, и весь фрагмент в вопросе сводится к следующему:
ai.[Due Date] AS [TD]
В столбце уже используется тип из семейства DateTime
, но клиентская система не может отформатировать
Это все еще довольно хорошо.Схема все еще в порядке, и в этом случае мы все еще можем несколько упростить исходный код:
COALESCE(
CASE WHEN ai.[Due Date] < GETDATE() THEN '[due] ' ELSE '' END
+ FORMAT(ai.[Due Date], 'MM-dd-yyyy')
, ' ') AS [TD]
В столбце используется тип a из семейства varchar
, но вы можете исправить это, используя DateTime2
Я говорю здесь "исправить", потому что теперь схема действительно сломана как есть.Но это нормально: вы можете это исправить. Сделайте это. Затем используйте код из предыдущего сценария.
В столбце используется тип из семейства varchar
, и вы не можете это исправить, но по крайней мере исходные данные всегдаиспользует семантический формат 'yyyy-MM-dd`
Bummer.Вы застряли с нарушенной схемой.Но мы можем, по крайней мере, воспользоваться хорошо отформатированными данными, чтобы сделать вещи намного более эффективными, используя приведение / преобразование выражения get_date()
для соответствия столбцу, а не наоборотнаоборот, как сейчас, вот так:
WHEN ai.[Due Date] < CONVERT(varchar, GETDATE(), 120)
Теперь мы проводим сравнение строк вместо сравнения дат, которое, как правило, медленнее и, ну, просто неправильно.Но мы можем обойтись без этого благодаря хорошему формату данных, и экономия заключается в том, что нам нужно привести только одно значение get_date()
, а не в каждой отдельной строке .Более того, таким образом любой индекс в столбце все равно будет действительным.Фрагмент кода в вопросе не сможет использовать индекс для столбца [Due Date]
.Я знаю, что это предложение SELECT
, но это стоит запомнить для общего случая.
Полное решение для этого сценария теперь выглядит следующим образом:
COALESCE(
CASE WHEN ai.[Due Date] < CONVERT(varchar, GETDATE(), 120) THEN '[due] ' ELSE '' END
+ FORMAT(CAST(ai.[Due Date]) AS Date), 'MM-dd-yyyy')
, ' ') AS [TD]
Опять же, только делайте это, если вы не можете получить необработанные данные столбца в формате DateTime
.Это то, что вы действительно хотите здесь.
В столбце используется тип a из семейства varchar
, вы не можете это исправить, а формат не семантический или непоследовательный
О, мальчик,Это то, где вы действительно не хотите быть.Если вы ничего не можете сделать, по минимум посмотрите, сможете ли вы начать получать последовательные и семантические значения в свой столбец.На этом этапе мы застряли с дополнительной работой над каждой строкой (возможно, более одного раза) для почти каждого запроса.Здесь мы говорим:
COALESCE(
CASE WHEN CAST(ai.[Due Date] AS DATETIME2) < GETDATE() THEN '[due] ' ELSE '' END
+ FORMAT(CAST(ai.[Due Date] AS DATETIME2), 'MM-dd-yyyy')
, ' ') AS [TD]
Код не сильно отличается от других вариантов, но характеристики производительности будут крайне отличаться ... потенциально на несколько порядков хуже.
Помните: из-за проблем интернационализации и часовых поясов преобразование между строками и датами на удивление медленное и дорогое.Старайтесь не делать этого по возможности во всех ваших запросах.