我无法确定仅根据月份和年份比较SQL日期的最佳方法。
我们根据日期进行计算,因为按月计费,每月的日期会造成更多障碍。
例如
DECLARE @date1 DATETIME = CAST('6/15/2014' AS DATETIME),
@date2 DATETIME = CAST('6/14/2014' AS DATETIME)
SELECT * FROM tableName WHERE @date1 <= @date2
上面的示例不会返回任何行,因为@ 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
我已完成日期的内联转换,以获得指定日期的第一天和最后一天。
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
必须有一种更简单的方法来做到这一点。有什么建议吗?
答案 0 :(得分:20)
要处理不等式,例如之间,我喜欢将日期/时间转换为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;
我会将查询写成:
SELECT *
FROM tableName
WHERE year(@date2) * 100 + month(@date2) BETWEEN year(@date1) * 100 + month(@date1) AND
year(@date3) * 100 + month(@date1);
答案 1 :(得分:15)
您可以将指定日期的月份和年份过滤到当前日期,如下所示:
SELECT *
FROM tableName
WHERE month(date2) = month(getdate()) and year(date2) = year(getdate())
只需将GETDATE()
方法替换为您想要的日期。
答案 2 :(得分:8)
SELECT *
FROM tableName
WHERE YEAR(@date1) = YEAR(@date2) AND MONTH(@date1) = MONTH(@date2)
答案 3 :(得分:8)
首先,我会使用明确的日期格式,例如标准'YYYYMMDD'
,而不是您一直使用的'6/15/2014'
。 Aaron Bertrand的博客解释得比我更好,这可能是出错的各种方式:
的 Bad habits to kick : mis-handling date / range queries 强>
对于特定问题,我的最后查询找到了月份的第一天和最后几天(对于date1和date3),在我看来是正确的轨道。您只需要几个月的第一天(date1的第一天和date3的下个月的第一天),如果您避开 evil BETWEEN
: What do BETWEEN and the devil have in common? 强>
SELECT *
FROM tableName
WHERE date2 >= DATEADD(month, DATEDIFF(month, '19000101', @date1), '19000101')
AND date2 < DATEADD(month, 1+DATEDIFF(month, '19000101', @date3), '19000101') ;
无论date2
(DATE
,DATETIME
,DATETIME2
或SMALLDATTEIME
的数据类型如何,查询都按原样运行。
奖励点,优化器会以这种方式考虑date2
上的索引。
改进,根据(但另一个)Aaron的博客文章,以避免在使用DATEDIFF()
评估表达式时基数估计的问题:
Performance Surprises and Assumptions : 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))) ;
答案 4 :(得分:1)
这是一道经典的数学题。很容易将月份与月份进行比较。那就是将年份与一年中的月数相乘,然后将一年中的月份相加。这将给出一个可以在一个范围内进行比较的整数。
例如:2021 年 7 月将是 07+12*2021
答案 5 :(得分:0)
您可以使用类似“ yyyyMM”的格式设置日期格式,因此只会选择同一年的月份。
SELECT *
FROM tableName
WHERE FORMAT(date_month_bill, 'yyyyMM') < FORMAT(DATEADD(MONTH, -1, GETDATE()), 'yyyyMM')
AND FORMAT(date_month_bill, 'yyyyMM') > FORMAT(DATEADD(MONTH, -3, GETDATE()), 'yyyyMM')
答案 6 :(得分:0)
我使用EOMONTH()将日期滚动到同一日期,并进行了比较。因此,如果我将date1作为09/18/2019和date2作为09/16/2019,它们都将累积到09/30/2019。这不是您问题的直接答案,但在我的情况下有效。