基于多条件的SQL日期筛选问题:按时间范围选择周/月数据
问题与解决方案
需求说明
我有一张存储每周日期的表,需要按以下规则筛选日期:
- 若日期距今不足2个月,保留所有周日期;
- 若日期距今超过2个月,仅保留每个月的最后一天。
尝试的错误SQL
我写了如下SQL,但执行失败:
SELECT DISTINCT(Date) FROM [Table] WHERE Date IN (CASE WHEN Date> DATEADD(month, -2, GETDATE()) THEN Date ELSE MAX(Date) GROUP BY Month(Date),Year(Date) );
错误提示:
Incorrect syntax near the keyword 'GROUP'.
示例场景
假设当前日期为2022年9月13日,距今2个月的分界日期为2022年7月13日。表中包含以下日期:
- 2022/05/06
- 2022/05/13
- 2022/05/20
- 2022/05/31
- 2022/06/07
- 2022/06/10
- 2022/06/17
- 2022/06/24
- 2022/06/30
- 2022/07/08(早于2022/07/13)
- 2022/07/15(晚于2022/07/13)
- 2022/07/22
- 2022/07/29
- 2022/08/05
- 2022/08/12
- 2022/08/19
- 2022/08/26
期望筛选结果:
- 2022/05/31
- 2022/06/30(早于2022/07/13)
- 2022/07/15(晚于2022/07/13)
- 2022/07/22
- 2022/07/29
- 2022/08/05
- 2022/08/12
- 2022/08/19
- 2022/08/26
正确SQL实现
原SQL的问题是CASE表达式不能嵌套GROUP BY聚合逻辑,CASE是行级判断,无法处理分组操作。根据需求,我们可以用OR连接两个筛选条件,结合EOMONTH()函数实现:
SELECT DISTINCT Date FROM [Table] WHERE -- 保留距今不足2个月的所有日期 Date > DATEADD(month, -2, GETDATE()) OR -- 保留距今超过2个月且为当月最后一天的日期 ( Date <= DATEADD(month, -2, GETDATE()) AND Date = EOMONTH(Date) ) ORDER BY Date;
逻辑解释
DATEADD(month, -2, GETDATE())计算出距今2个月的分界日期;EOMONTH(Date)返回该日期所在月份的最后一天,通过Date = EOMONTH(Date)判断当前日期是否为当月最后一天;- 两个条件用
OR连接,同时覆盖两种筛选规则; DISTINCT用于确保结果无重复日期,ORDER BY Date让结果按时间排序。
兼容旧版本SQL(无EOMONTH函数)
如果你的SQL环境不支持EOMONTH()(比如SQL Server 2008及更早),可以用以下表达式替代EOMONTH(Date):
DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, Date) + 1, 0))
替代后的完整SQL:
SELECT DISTINCT Date FROM [Table] WHERE Date > DATEADD(month, -2, GETDATE()) OR ( Date <= DATEADD(month, -2, GETDATE()) AND Date = DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, Date) + 1, 0)) ) ORDER BY Date;
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

