比较一些基于月份 1 号的日期谓词

Compare some date predicate based on 1st of the month

我想从 getdate() 获取标题 (yyyy-mm) 中的 DATE 格式,以便在 where 子句中使用它从我格式化的日期中获取 < 和 > 日期。到目前为止我发现几乎每个人都使用 convert(varchar(10),getdate(),120) 但那是 varchar 并且不能用 < 和 > 进行检查,对吗?那么有人可以帮我制作一个 yyyy-mm 格式的日期吗?或者这是不可能的?

为什么不能使用 > 和 < 运算符比较 VARCHAR?只要你有一个适当格式的字符串,你就可以很好地比较它。例如,CONVERT(VARCHAR(10), GETDATE(), 120) returns ODBC 规范格式日期,如 "YYYY-MM-DD"。这显然可以使用 > 和 < 进行比较以获得正确的结果。

但是,您通常不想在数据库中执行此操作。像这样的谓词:

WHERE CONVERT(VARCHAR(10), [DateColumn], 120) >= '2018-02-26'

被认为是 "non-SARGable",不能使用索引。这意味着服务器将在比较之前对基础列应用强力转换,从而导致索引扫描或 Table 扫描,具体取决于您的架构。

对于绝大多数情况,您希望将列用作操作数,而无需事先进行任何类型的转换。因此,谓词应表示为:

WHERE [DateColumn] >= '2018-02-26'

这将导致将“2018-02-26”操作数隐式转换为 Date 或 DateTime(无论列类型是什么),并且这可以使用索引。

绝对最好的是像这样的显式转换:

WHERE [DateColumn] >= CAST('2018-02-26' AS DATETIME)

这样,就没有错误、隐式转换或 non-SARGable 谓词的余地。

简而言之,您不想按照您要求的方式执行此操作。

要查找与特定年份和月份匹配的记录,只需以这种方式使用两个 where 条件:

declare @SomeDate date = '20180114';    -- This is any date.
-- This gets the first day of the month of the date above.
declare @MonthStart date = dateadd(month,datediff(month,0,@SomeDate),0);
-- This gets the first day of the following month of the date above.
declare @NextMonthStart date = dateadd(month,datediff(month,0,@SomeDate)+1,0);

select cols
from tables
where DateCol >= @MonthStart
  and DateCol < @NextMonthStart;

如果您有一个现有的日期时间,您应该将它与另一个时间进行比较,例如使用 between。为什么要做字符串比较