Почему мое предложение WHERE не распознает поле как дату, даже после преобразования этого поля из int в date?

#sql-server #tsql #casting #where-clause

#sql-server #tsql #Кастинг #where-предложение

Вопрос:

Я выполнил следующий оператор SELECT в SQL Server, который выдает ошибку:

Ошибка арифметического переполнения при преобразовании выражения в тип данных datetime.

 SELECT Id, CAST(CAST(CalendarDate as varchar(10)) as date)
FROM dbo.Sales
WHERE CalendarDate BETWEEN dateadd(month,-6, GETDATE()) AND (GETDATE())
 

Id = уникальный идентификатор

CalendarDate = int , которое мне нужно преобразовать в date .

Что я делаю не так?

Я хочу найти все даты между сегодняшней датой и 6 месяцами назад, однако я получаю указанную ошибку.

Любая помощь приветствуется.

Спасибо.

Комментарии:

1. int и date / datetime или — это два очень разных типа. Какое преобразование вы бы хотели, чтобы оно произвело?

2. ДА. Оба типа данных, которые вы пытаетесь сравнить, различны и несовместимы. Какие данные у вас есть в столбце CalendarDate ?

3. Я хочу перейти от int к date, как я уже писал. Я также попытался использовать значение datetime. По-прежнему не работает. В столбце CalendarDate у меня есть такие данные, как «20200821» в качестве int. Это в основном ггггммдд.

4. Просто попробуйте WHERE msdb.dbo.agent_datetime(CalendarDate,0) BWTEEEN …..

5. Правила для приоритета типов данных показывают, что если вы объединяете an int и a datetime в выражении, то int оно преобразуется в a datetime . Плохая новость в том, что 20200821 это не означает, что вы этого хотите : select Cast( 0 as DateTime ) as BaseDate, Cast( 1 as DateTime ) as OneDayLater; . Вам нужно будет выбрать свою int часть и собрать ее заново, например, с DateFromParts помощью .

Ответ №1:

Попробуйте преобразовать границы даты в предложении WHERE следующим образом:

 SELECT Id, CAST(CAST(CalendarDate as varchar(10)) as date)
FROM dbo.Sales
WHERE CalendarDate BETWEEN CAST(CONVERT(CHAR(8),dateadd(month,-6, GETDATE()),112)  AS INT) and CAST(CONVERT(CHAR(8),GETDATE(),112) AS INT)
 

Комментарии:

1. Ответ найден, но не подход SQLServerBuddy для использования «ГДЕ msdb.dbo.agent_datetime(CalendarDate,0) BWTEEEN …» также работает.

2. Изменяя значение столбца, вы потеряете возможность использовать индекс для этого столбца. Кроме того, это подразумевает больше вычислений — больше использования ЦП.

Ответ №2:

Поскольку предложение Where вычисляется перед предложением select , таким образом, преобразованное поле не распознается, потому что оно еще не существует.

На основе https://docs.microsoft.com/en-us/sql/t-sql/queries/select-transact-sql?view=sql-server-ver15#logical-processing-order-of-the-select-statement , порядок вычисления запроса следующий :

Логический порядок обработки инструкции SELECT Следующие шаги показывают логический порядок обработки или порядок привязки для инструкции SELECT. Этот порядок определяет, когда объекты, определенные на одном шаге, становятся доступными для предложений на последующих шагах. Например, если обработчик запросов может привязываться (получать доступ) к таблицам или представлениям, определенным в предложении FROM , эти объекты и их столбцы становятся доступными для всех последующих шагов. И наоборот, поскольку предложение SELECT является шагом 8, на любые псевдонимы столбцов или производные столбцы, определенные в этом предложении, не могут ссылаться предыдущие предложения. Однако на них могут ссылаться последующие предложения, такие как предложение ORDER BY . Фактическое физическое выполнение инструкции определяется обработчиком запросов, и порядок может отличаться от этого списка.

  1. От
  2. НА
  3. Присоединиться
  4. ГДЕ
  5. ГРУППИРОВАТЬ ПО
  6. С ПОМОЩЬЮ КУБА или С ПОМОЩЬЮ СВЕРТКИ
  7. ИМЕЯ
  8. ВЫБЕРИТЕ
  9. DISTINCT
  10. ПОРЯДОК ПО
  11. НАВЕРХ