我不明白为什么日期时间字段的查询过滤在 sql 服务器 2016 上不起作用

i can not understand why a query filtering on datetime field is not working on sql server 2016

这是一个非常基本的查询:

select * from [dbo].[TestTable]  where year(start_date)>2021

它 return 没有记录,start_date 是日期时间,table 包含许多记录,该字段已增值且日期超过 2021 年。

本查询return的所有记录 table:

SELECT year(start_date), * FROM [dbo].[TestTable] order by start_date desc

这是 table 结构:

另一个结果奇怪的查询:

SELECT year(start_date), case when year(start_date)>2021 then 1 else 0 end, * FROM [ADS].[dbo].[TestTable] order by start_date desc

我可以检查什么?

您缺少运算符的 = 部分。所有行似乎都有 2021-01-01,所以 YEAR 不大于 2021,是 2021。

你需要做

select * from [dbo].[TestTable]  where year(start_date)>=2021

select * from [dbo].[TestTable]  where year(start_date)=2021

正如 Dan Guzman 指出的那样,作为一项额外的改进,您应该避免在 WHERE 子句上使用函数,因为这会阻止索引的使用,因为它需要对 [=24 上的每一行执行函数=] 以便能够确定它是否匹配。

如果就记录数而言,table 很小,这没什么大不了的,但如果您谈论的是数万或更多,那就会加起来了。

备选方案是按原始日期值过滤,或者将年份保存为单独的字段并为其添加索引。

一切正常。 None 图片中的结果包含记录 where year(start_date)>2021.

所以我认为您可能会查找开始日期大于 2020 年的行

select * from [dbo].[TestTable]  where year(start_date)>2020

或 select * 来自 [dbo].[TestTable] 其中年份 (start_date)>=2021

或者正如@Dan Guzman 所建议的,最好使用:

select * from [dbo].[TestTable]  where start_date>='2021-01-01'

table 中没有任何内容的年份 > 2021。日期 大于年份的 开始,但是如果只看年份,它们 等于 2021,而不是更大。

为了解决这个问题,我将完全删除 year() 函数。在列上调用函数可能 对性能不利 ,因为它会影响在列上使用索引的能力。这个可能并不糟糕(year()deterministic,所以有时索引仍然可以),但如果有一种方法可以在没有函数的情况下表达查询,那通常是个好主意。在这种情况下,我们可以这样做:

select * from [dbo].[TestTable]  where start_date >= '20210101'