#sql #sql-server #date-formatting
#sql #sql-сервер #форматирование даты
Вопрос:
Я пытаюсь выполнить запрос с помощью SQL Server Management Studio 2017, который возвращает количество всех серверов с прогнозируемой датой миграции в этом году. У меня есть один запрос, сделанный сейчас, но он все еще возвращает некоторые серверы с датами за предыдущие годы.
SELECT MONTH(Projected) as [Month], count(*) as [Total]
FROM dbo.tFake
WHERE Projected >='01/01/2019' AND Projected <='12/31/2019
GROUP BY Month(Projected)
ORDER BY [Month]
Формат даты — mm/dd/yyyy
кстати. Как я могу заставить этот запрос вернуть только серверы, которые запланированы на 2019 год?
Комментарии:
1. Добро пожаловать в Stack Overflow! У вас незакрытые кавычки, хотя я подозреваю, что это опечатка, поскольку написанный код не будет выполняться. Пожалуйста, опубликуйте образец данных, который возвращает серверы за пределами вашего диапазона дат. Вы также могли бы попробовать «Где год (прогнозируемый) = 2019» вместо двух сравнений дат.
2. Что вы имеете в виду под форматом даты
mm/dd/yyyy
? Типы данных даты и времени не имеют формата в SQL Server. Вы не храните даты, хранящие даты какvarchar
не так ли? avarchar
— это не дата, и это объясняет, почему вы получаете неправильные данные; вы выбрали неправильный тип данных. Например, с помощью avarchar
утверждение'12/01/2000' > '01/01/2019'
является истинным . Почему? Потому чтоvarchar
сравниваются с использованием их символов слева направо. Поскольку'1' > '0'
это означает, что'12/01/2000' > '01/01/2019'
.
Ответ №1:
Исходя из предположения, что ваш тип данных неверен, первым шагом является исправление этого. Обратите внимание, я предполагаю, что ваши данные содержат только даты, а не время (что подразумевает ваш запрос). Во-первых, вам нужно изменить значение всех ваших строк на конвертируемое значение, мы будем использовать формат ISO yyyyMMdd
:
UPDATE dbo.tFake
SET Projected = CONVERT(varchar(8),CONVERT(date,Projected,101),112);
Теперь, когда все строки представляют собой буквенную строку в формате yyyyMMdd
, мы можем изменить столбец:
ALTER TABLE dbo.tFake ALTER COLUMN Projected date;
Теперь мы можем снова выполнить ваш запрос, но теперь ваш тип данных правильный, у вас не возникнет проблемы:
SELECT MONTH(Projected) as [Month], count(*) as [Total]
FROM dbo.tFake
WHERE Projected >= '20190101' AND Project < '20200101' --I prefer the >= and < method. This is especially import with date amp; time data types
GROUP BY Month(Projected)
ORDER BY [Month];
Обратите внимание, что литеральные строки, которые я передал, также находятся в yyyyMMdd
формате. Если вам необходимо передать литеральную строку в формате, MMddyyyy
который вы можете обернуть в CONVERT
с помощью кода стиля 101
: CONVERT(date,'12/31/2019',101)
. 101
означает дату в американском стиле (ПРИВЕДЕНИЕ и ПРЕОБРАЗОВАНИЕ (Transact-SQL).
Помните, что это решение предполагает, что у вас есть значения только даты, а не значения даты и времени. Если вы это сделаете (у вас есть значения даты и времени), вы захотите использовать соответствующий тип данных даты и времени и использовать стиль ISO8601 вместо стиля ISO.
Комментарии:
1. Это определенно помогло! Я смог заставить запрос вернуть именно то, что я хотел. Спасибо!
2. Добро пожаловать @ScaredIntern . Пожалуйста, отметьте ответ как решение, если это решило вашу проблему, чтобы будущие читатели знали, что ответ помог. Спасибо.