Форматирование даты TSQL в мм-дд-гггг - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть дата в формате Datetime2, и она выглядит как гггг-мм-дд.Есть ли способ переформатировать его, чтобы он был мм-дд-гггг?

                CASE 
                WHEN CAST(ai.[Due Date] AS DATETIME2)  < GETDATE() THEN '[due]' + LEFT((ai.[Due Date]),10)
                WHEN CAST(ai.[Due Date] AS DATETIME2) IS NULL THEN ' '
                ELSE LEFT((ai.[Due Date]),10)
            END AS [TD]

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

Вы неправильно понимаете, как значения даты работают в базе данных. Нет читаемого человеком формата .Когда вы видите 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]

Код не сильно отличается от других вариантов, но характеристики производительности будут крайне отличаться ... потенциально на несколько порядков хуже.

Помните: из-за проблем интернационализации и часовых поясов преобразование между строками и датами на удивление медленное и дорогое.Старайтесь не делать этого по возможности во всех ваших запросах.

0 голосов
/ 15 февраля 2019

Традиционным способом является использование convert():

convert(varchar(10), ai.[Due Date], 110)

Более универсальный метод использует format():

select format(ai.[Due Date], 'dd-MM-yyyy')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...