Тип операнда clash: дата несовместима с int? - PullRequest
1 голос
/ 17 июня 2019

Может кто-нибудь помочь мне, у меня есть следующий TSQL, который выдает ошибки (это часть табличного представления).

SELECT MAX([WEEK]) FROM MyTable WHERE [Year] = DATEPART(YYYY, GETDATE())

Это часть оператора просмотра вида как такового:

CASE 
    WHEN [WEEK] <= (SELECT MAX([WEEK]) FROM MyTable WHERE [Year] = DATEPART(YYYY, GETDATE())) THEN 
        [YEAR]
END YTD,

Это приводит к ошибке: Столкновение с типом операнда: дата несовместима с int

Таблица определяется как:

CREATE TABLE [dbo].[MyTable](
  [Week] [tinyint] NULL,
  [Year] [date] NULL,
) ON [PRIMARY]
GO

Как заставить TSQL работать без изменения типа поля таблицы?

Поле [Год] содержит записи в формате ГГГГ-ММ-ДД.

Это на SQL Server 2016.

1 Ответ

0 голосов
/ 18 июня 2019

Вызов date столбца year - очень плохой выбор имени.
Выражение SQL, которое вы опубликовали, кажется вполне разумным - поскольку, когда вы видите столбец с именем year, вы ожидаете, что он будет содержать год (то есть int), а не значение даты.

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

Таким образом, функция Year() возвращает значение типа int - и, естественно, такое значение нельзя сравнить со значением даты. - Как бы вы сравнили 532 с 1 мая 2019 года? это сравнивает яблоки с апельсинами.

У вас есть опция SARGable и опция без SARGable для решения этой проблемы.
В двух словах - SARGable означает условие, которое позволяет ядру базы данных использовать поиск по индексу, когда существует соответствующий индекс.

Параметр non-SARGable - это то, что Джон Каппеллетти предложил в своем комментарии - используйте datepart как для столбца, так и для значения:

 WHERE datepart(YEAR,[Year]) = DATEPART(YEAR, GETDATE())

Это хороший вариант, если у вас нет индекса в столбце года или таблица не очень большая, поэтому сканирование индекса по сравнению с поиском по индексу на самом деле не является проблемой, или если скорость выбора не является проблемой.

Опция SARGable заключается в использовании несколько иного условия - как HABO, предложенный в его комментарии (хотя я думаю, что моя версия немного проще):

WHERE [Year] => DATEFROMPARTS(DATEPART(YEAR, GETDATE()), 1, 1)
AND [Year] < DATEFROMPARTS(DATEPART(YEAR, GETDATE()) + 1, 1, 1)

Это лучший вариант, если у вас есть индекс для столбца Year, а таблица достаточно велика, чтобы сканирование индекса по сравнению с поиском индекса оказало достаточно значительное влияние на производительность выбора.

...