SQL Server日期比较仅基于月份和年份

And*_*ans 18 sql sql-server date sql-server-2008

我无法确定仅基于月份和年份比较SQL中日期的最佳方法.

我们根据日期进行计算,并且由于按月计费,因此该月的日期会造成更多障碍.

例如

DECLARE @date1 DATETIME = CAST('6/15/2014' AS DATETIME),
        @date2 DATETIME = CAST('6/14/2014' AS DATETIME)

SELECT * FROM tableName WHERE @date1 <= @date2
Run Code Online (Sandbox Code Playgroud)

上面的示例不会返回任何行,因为@ date1大于@ date2.所以我想找到一种方法来摆脱这个等式.

同样,以下情况也让我悲伤同样的原因.

DECLARE @date1 DATETIME = CAST('6/14/2014' AS DATETIME),
        @date2 DATETIME = CAST('6/15/2014' AS DATETIME),
        @date3 DATETIME = CAST('7/1/2014' AS DATETIME)

SELECT * FROM tableName WHERE @date2 BETWEEN @date1 AND @date3
Run Code Online (Sandbox Code Playgroud)

我已完成日期的内联转换,以获得指定日期的第一天和最后一天.

SELECT * 
FROM tableName 
WHERE date2 BETWEEN
    DATEADD(month, DATEDIFF(month, 0, date1), 0) -- The first day of the month for date1
    AND
    DATEADD(s, -1, DATEADD(mm, DATEDIFF(m, 0, date2) + 1, 0)) -- The lastday of the month for date3
Run Code Online (Sandbox Code Playgroud)

必须有一种更简单的方法来做到这一点.有什么建议?

Gor*_*off 21

为了处理不等式,例如之间,我喜欢将日期/时间转换为YYYYMM表示,可以是字符串也可以是整数.对于这个例子:

DECLARE @date1 DATETIME = CAST('6/14/2014' AS DATETIME),
        @date2 DATETIME = CAST('6/15/2014' AS DATETIME),
        @date3 DATETIME = CAST('7/1/2014' AS DATETIME);

SELECT * FROM tableName WHERE @date2 BETWEEN @date1 AND @date3;
Run Code Online (Sandbox Code Playgroud)

我会把查询写成:

SELECT *
FROM tableName
WHERE year(@date2) * 100 + month(@date2) BETWEEN year(@date1) * 100 + month(@date1) AND
                                                 year(@date3) * 100 + month(@date1);
Run Code Online (Sandbox Code Playgroud)


Tan*_*ner 15

您可以将给定日期的月份和年份过滤到当前日期,如下所示:

SELECT * 
FROM tableName 
WHERE month(date2) = month(getdate()) and year(date2) = year(getdate())
Run Code Online (Sandbox Code Playgroud)

只需将GETDATE()方法替换为您想要的日期即可.


Dav*_*idG 9

您可以加入这些日期MONTHYEAR价值观:

SELECT * 
FROM tableName 
WHERE YEAR(@date1) = YEAR(@date2) AND MONTH(@date1) = MONTH(@date2)
Run Code Online (Sandbox Code Playgroud)


ype*_*eᵀᴹ 8

首先,我会使用明确的日期格式,例如标准'YYYYMMDD'而不是'6/15/2014'您一直使用的格式.Aaron Bertrand的博客解释得比我想象的要好得多,这可能是出错的各种方法:
糟糕的习惯:错误处理日期/范围查询

对于特定问题,我的最后查询找到了月份的第一天和最后几天(对于date1和date3),在我看来是正确的轨道.你只需要几个月的第一天(date1的第一天和date3的下个月的第一天),如果你避开邪恶BETWEEN: BETWEEN和魔鬼有什么共同之处?

SELECT * 
FROM tableName 
WHERE date2 >= DATEADD(month, DATEDIFF(month, '19000101', @date1), '19000101')
  AND date2 < DATEADD(month, 1+DATEDIFF(month, '19000101', @date3), '19000101') ;
Run Code Online (Sandbox Code Playgroud)

该查询工作,因为它是,无论的数据类型date2(DATE,DATETIME,DATETIME2SMALLDATTEIME).

奖励点,date2优化器将以这种方式考虑索引.


根据(另一个)Aaron的博客文章,改进,以避免在评估表达式时基数估计的问题DATEDIFF():
性能惊喜和假设:DATEDIFF

SELECT * 
FROM tableName 
WHERE date2 >= CONVERT(DATE, DATEADD(day, 1 - DAY(@date1), @date1))
  AND date2 < DATEADD(month, 1, 
                      CONVERT(DATE, DATEADD(day, 1 - DAY(@date3), @date3))) ;
Run Code Online (Sandbox Code Playgroud)