Oracle CASE语句结合日期查询报错及需求实现求助
问题分析与解决
原查询的核心问题是Oracle的CASE表达式无法直接返回布尔类型结果,你试图在THEN后直接写条件表达式,这不符合Oracle语法规则。另外原语句中存在无意义的TO_CHAR(MYDATE...) != TO_CHAR(MYDATE...)(永远为假),以及多余的括号,这些都是报错的原因。
根据你的需求(周一查过去2天内不含当天的数据,周二至周六查过去1天内不含当天的数据),提供两种可行写法:
写法一:直接用逻辑条件组合(推荐,可读性更高)
SELECT ID, MYDATE FROM MY_DATABASE WHERE -- 排除当天数据 TRUNC(MYDATE) < TRUNC(SYSDATE) AND ( -- 周一(TO_CHAR(SYSDATE,'D')='2'):MYDATE大于2天前的零点 (TO_CHAR(SYSDATE, 'D') = '2' AND MYDATE >= TRUNC(SYSDATE) - 2) OR -- 周二至周六(TO_CHAR(SYSDATE,'D')在'3'-'7'):MYDATE大于1天前的零点 (TO_CHAR(SYSDATE, 'D') IN ('3','4','5','6','7') AND MYDATE >= TRUNC(SYSDATE) - 1) );
- 使用
TRUNC(SYSDATE)获取当天零点,TRUNC(MYDATE) < TRUNC(SYSDATE)确保排除当天的数据 - 根据星期几的判断,分别设置不同的时间范围条件,逻辑清晰,性能更优
写法二:用CASE表达式返回数值判断
如果一定要用CASE,可以将条件转换为数值返回,再判断是否符合:
SELECT ID, MYDATE FROM MY_DATABASE WHERE TRUNC(MYDATE) < TRUNC(SYSDATE) AND CASE WHEN TO_CHAR(SYSDATE, 'D') = '2' THEN CASE WHEN MYDATE >= TRUNC(SYSDATE) - 2 THEN 1 ELSE 0 END WHEN TO_CHAR(SYSDATE, 'D') IN ('3','4','5','6','7') THEN CASE WHEN MYDATE >= TRUNC(SYSDATE) - 1 THEN 1 ELSE 0 END ELSE 0 END = 1;
- 内层CASE将时间范围判断转换为1/0的数值,外层CASE根据星期几选择对应的判断逻辑,最后判断等于1来筛选数据
额外提示
TO_CHAR(SYSDATE, 'D')的返回值依赖于Oracle的NLS_TERRITORY设置,如果你的环境中周一对应的不是'2',可以用固定语言的星期缩写来避免地域影响:
-- 替换星期判断部分,更稳定 TO_CHAR(SYSDATE, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') = 'MON'
内容的提问来源于stack exchange,提问作者eli nollan gonzalez
相关产品推荐
相关产品推荐

