Spark SQL中获取指定月份最近一次出现数据的最简方法及可读SQL编写方案
解决Spark SQL中获取指定月份最近一次数据的最简可读写法
嘿,我来帮你搞定这个问题!首先你之前的SQL语句跑不起来,核心原因是CASE语句缺少了END关键字——这是Spark SQL的语法要求,必须用END来闭合CASE逻辑,不然解析器会直接报错。
接下来给你两种高可读性的实现方式,完美匹配你的需求:输入一个月份,自动匹配最近一次出现该月份的年份(当前年或前一年),筛选对应数据。
方式一:直接构造目标月份(最直观推荐)
这种写法通过构造目标月份的起始日期,直接和DateF的月份起始做匹配,逻辑清晰直白,不容易出错:
-- 把@target_month替换成你需要的月份数字(比如11代表11月) SELECT * FROM your_table WHERE date_trunc('month', DateF) = date_trunc('month', make_date( -- 判断目标月份是否晚于当前月份,是的话取前一年,否则取当前年 CASE WHEN @target_month > month(current_date()) THEN year(current_date()) - 1 ELSE year(current_date()) END, @target_month, 1 ) )
逻辑拆解:
make_date():根据计算出的年份、目标月份,生成该月份的第一天(比如2023-11-01)date_trunc('month', ...):把日期统一截断到月份起始,这样只要DateF落在目标月份里,截断后就会和目标日期完全相等- 整个WHERE条件清晰表达了“筛选目标月份对应年份的所有数据”的核心需求
方式二:拆分年月比较(兼容旧版Spark)
如果你使用的Spark版本不支持make_date()(比如2.x早期版本),可以用拆分年月的方式,同时修正你原来的CASE语法问题:
-- 把@target_month替换成目标月份 SELECT * FROM your_table WHERE month(DateF) = @target_month AND year(DateF) = CASE WHEN @target_month > month(current_date()) THEN year(current_date()) - 1 ELSE year(current_date()) END -- 这里必须加END,就是你之前漏掉的关键部分!
关键修正说明:
你之前的代码就是少了END,导致CASE语句不完整,Spark无法正常解析。加上END后,语法完全合规,逻辑也能按预期运行。
额外优化:如果需要取该月份的最新单条数据
如果你的需求是获取目标月份里的最新一条数据,可以在上面的基础上加上排序和限制:
SELECT * FROM your_table WHERE date_trunc('month', DateF) = date_trunc('month', make_date( CASE WHEN @target_month > month(current_date()) THEN year(current_date()) - 1 ELSE year(current_date()) END, @target_month, 1 ) ) ORDER BY DateF DESC LIMIT 1
这样就能拿到目标月份里时间最晚的那条记录啦。
内容的提问来源于stack exchange,提问作者Lord_JABA




