关于SQL查询财年(4月至次年3月)数据的技术问询
分析两段SQL的有效性及正确写法
首先直接给结论:你提供的两段SQL都无法正确查询到目标财年的数据,问题出在STR_TO_DATE函数的格式符使用错误上。咱们逐个拆解:
第一段SQL的问题
SELECT * FROM `uts` WHERE MONTH_YEAR BETWEEN STR_TO_DATE('Apr-16','%m-%y') and STR_TO_DATE('Mar-17','%m-%y')
这里的核心错误是用了%m格式符来解析英文月份缩写(比如Apr)。在MySQL的STR_TO_DATE函数里,%m代表的是数字格式的月份(01-12),而非英文缩写。当你尝试用%m-%y解析Apr-16时,MySQL无法把Apr转换成合法的数字月份,会直接返回NULL。
这样一来,你的BETWEEN条件就变成了NULL BETWEEN NULL AND NULL,这个判断永远为false,最终查不到任何数据。
第二段SQL的问题
select * from uts where month_year is not null and (str_to_date(concat('01-',month_year),'%d-%m-%y') between str_to_date('01-apr-16','%d-%m-%y') and str_to_date('31-mar-17','%d-%m-%y'))
这段SQL的思路是对的——通过拼接01-来构造完整的日期字符串,方便进行范围比较,但同样犯了格式符的错误:%m依然对应数字月份,而你的month_year是Apr-16这种英文缩写格式,所以str_to_date(concat('01-',month_year),'%d-%m-%y')还是会解析失败,返回NULL,导致条件不成立,同样查不到数据。
正确的SQL写法
你需要把格式符换成%b(代表英文月份缩写,比如Jan、Apr),同时%y对应两位年份,这样才能正确解析01-Apr-16这类字符串。正确的查询语句如下:
SELECT * FROM uts WHERE month_year IS NOT NULL AND STR_TO_DATE(CONCAT('01-', month_year), '%d-%b-%y') BETWEEN STR_TO_DATE('01-Apr-16', '%d-%b-%y') AND STR_TO_DATE('31-Mar-17', '%d-%b-%y');
额外注意事项
如果你的MySQL会话的locale不是英文,%b可能无法正确识别英文月份缩写。这种情况下,你可以先临时设置会话的locale,比如:
SET lc_time_names = 'en_US';
执行完这个语句后再运行查询,就能正常解析英文月份缩写了。
内容的提问来源于stack exchange,提问作者Om Bk
相关产品推荐
相关产品推荐

