You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

行转列查询水电费账单时varchar类型月份用BETWEEN无结果问题

问题原因分析

你遇到的无结果问题核心是ub.c_month为varchar类型,存储的是月缩写-年份后两位格式的字符串,使用BETWEEN做比较时遵循的是字典排序规则,而非时间顺序规则:

  • 你写的条件是ub.c_month BETWEEN 'Sep-21' AND 'Nov-21',按字典序字母S(对应Sep)的排序优先级高于N(对应Nov),Nov-21实际小于Sep-21,相当于你写了「值介于较大的字符串和较小的字符串之间」,自然不会返回任何结果。
  • 哪怕调整顺序写对了同一年内的比较,一旦涉及跨年份查询,比如查2021年11月到2022年1月,Nov-21字典序大于Jan-22,还是会出现无结果的问题,本质是该字符串格式无法正确匹配时间逻辑。
解决方案

方案1:将字符串转为日期类型后比较(推荐,兼容性最好)

根据你使用的数据库,把c_month字段转为日期类型再做范围判断,示例如下:

  • MySQL环境:
WHERE e.c_serviceNumber = 874256  
AND STR_TO_DATE(ub.c_month, '%b-%y') BETWEEN STR_TO_DATE('Sep-21', '%b-%y') AND STR_TO_DATE('Nov-21', '%b-%y')
  • Oracle环境:
WHERE e.c_serviceNumber = 874256  
AND TO_DATE(ub.c_month, 'MON-YY', 'NLS_DATE_LANGUAGE = AMERICAN') BETWEEN TO_DATE('Sep-21', 'MON-YY', 'NLS_DATE_LANGUAGE = AMERICAN') AND TO_DATE('Nov-21', 'MON-YY', 'NLS_DATE_LANGUAGE = AMERICAN')
  • SQL Server环境:
WHERE e.c_serviceNumber = 874256  
AND CONVERT(DATE, '01-' + ub.c_month, 6) BETWEEN CONVERT(DATE, '01-Sep-21', 6) AND CONVERT(DATE, '01-Nov-21', 6)

方案2:调整字符串顺序(临时方案,仅适用同一年查询)

如果暂时无法修改逻辑,且仅查询同一年内的月份,可以直接颠倒两个值的顺序,仅本次查询生效:

WHERE e.c_serviceNumber = 874256  
AND ub.c_month BETWEEN 'Nov-21' AND 'Sep-21'

注意:该方案仅适合同一年内、且起始月份字母排序大于结束月份的场景,跨年份查询一定会出错,不建议长期使用。

额外优化建议
  • 原SQL的GROUP BY子句中重复写了两次ub.c_month,可以删掉其中一个,不影响逻辑还能避免不必要的解析开销。
  • 原SELECT中的多个子查询每次都要扫描app_fd_pr_uage_catconfig表取分类名称,可以提前把分类和对应序号的映射关系查出来用JOIN关联,大幅提升查询效率。

内容的提问来源于stack exchange,提问作者Ahmed Akram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 10:24:04