【问题标题】:Operand type clash: date is incompatible with int?操作数类型冲突:日期与 int 不兼容?
【发布时间】:2019-10-31 08:06:21
【问题描述】:

谁能帮帮我,我有以下 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 工作?

[Year] 字段包含格式为 YYYY-MM-DD 的记录。

这是在 SQL Server 2016 上。

【问题讨论】:

  • 您的列 [Year] 是日期,而不是 int。 WHERE datepart(YEAR,[Year]) = DATEPART(YEAR, GETDATE())
  • 成功了,谢谢。
  • 或者使用Year():where Year( [Year] ) = Year( GetDate() )。请注意,这不是SARGABLE。如果有值得使用的索引,您可以使用where DateFromParts( Year( GetDate() ) - 1, 12, 31 ) &lt; [Year] and [Year] &lt; DateFromParts( Year( GetDate() ) + 1, 1, 1 )
  • 旁白:[Year] 列是Date,没有格式'YYYY-MM-DD' 是将Date 转换为字符串以进行显示时可能应用的多种格式之一。

标签: sql sql-server tsql sql-server-2016


【解决方案1】:

调用dateyear 是一个非常糟糕的命名选择。
您发布的 SQL 语句似乎完全合理 - 因为当您看到名为 year 的列时,您希望它包含年份(意思是一个 int),而不是包含日期值。

您应该考虑重命名该列或更改它的数据类型,只是为了节省一些时间,因为这个可怜的混蛋将不得不在一年后对该代码进行维护工作,因为它可能会是您。

话虽如此,Year() 函数返回一个 int 值 - 自然,这样的值无法与日期值进行比较 - 您如何将 532 与 2019 年 5 月 1 日进行比较?这就是将苹果与橙子进行比较。

您有一个 SARGable 选项和一个非 SARGable 选项来解决此问题。
简而言之 - SARGable 表示当存在相关索引时允许数据库引擎使用索引查找的条件。

非 SARGable 选项是 John Cappelletti 在 his comment 中建议的 - 对列和值都使用 datepart

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

如果您在年列中没有索引或者表不是很大,那么这是一个不错的选择,因此索引扫描与索引搜索并不是真正的问题,或者如果选择速度不是问题。

SARGable 选项是使用稍微不同的条件——比如his comment 中建议的 HABO(虽然我认为我的版本稍微简单一些):

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

当您在 Year 列上有索引并且表足够大以至于索引扫描与索引查找对选择性能有足够显着的影响时,这是一个更好的选择。

【讨论】:

    猜你喜欢
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 2021-09-24
    相关资源
    最近更新 更多