简体   繁体   中英

Operand type clash: date is incompatible with int?

Can someone help me out here, I have the following TSQL that is throwing errors (it is part of a table view).

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

This is part of a view case statement as such:

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

This throws an error: Operand type clash: date is incompatible with int

The table is defined as:

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

How can I make the TSQL work without changing the table field type?

The [Year] field contains records in the format of YYYY-MM-DD.

This is on a SQL Server 2016.

Calling a date column year is a very poor naming choice.
The SQL statement you've posted seems entirely reasonable - since when you see a column named year you expect it to contain the year (meaning, an int), not to contain a date value.

You should think of renaming that column or changing it's data type, just to save some time for the poor bastard that's going to have to do maintenance work on this code a year from now, since it's probably going to be you.

Than being said, the Year() function returns an int value - and naturally, such a value can't be compared to a date value - How would you compare 532 with May 1st 2019? that's comparing apples to oranges.

You have a SARGable option and a non-SARGable option to fix this problem.
In a nutshell - SARGable means a condition that allows the database engine to use an index seek, when a relevant index exists.

The non-SARGable option is what John Cappelletti suggested in his comment - use datepart for both the column and the value:

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

This is a good option if you don't have an index in the year column or the table is not very big so an index scan vs an index seek is not really an issue, or if select speed is not an issue.

The SARGable option is to use a slightly different condition - like HABO suggsted in his comment (though I think my version is slightly simpler):

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

This is a better option when you have an index on the Year column and the table is large enough so that index scan vs index seek would have a significant enough impact on the select performance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM