如何在Oracle SQL中提取当日当前班次的数据?
Oracle班次数据提取问题解决
原代码核心问题
- 非法时间提取语法:
SYSDATE(HHMM)是错误写法,Oracle没有这种直接提取时分的方式,必须通过TO_CHAR转换格式后再转数字。 - 逻辑优先级错误:夜班条件中的
OR和AND未加括号分组,导致过滤逻辑不符合跨天班次的需求。 - 纯SQL不支持直接IF-ELSE:原代码的IF-ELSE结构无法在纯SQL查询中直接使用,需整合到WHERE子句逻辑或改用PL/SQL实现。
纯SQL解决方案(推荐)
直接通过当前时间判断班次,整合逻辑到WHERE子句,无需分支语句:
SELECT * FROM your_table -- 替换为实际表名 WHERE -- 白班:当前时间0830-2030,取当日0830-2030的数据 (TO_NUMBER(TO_CHAR(SYSDATE, 'HH24MI')) BETWEEN 830 AND 2030 AND rej_date = TO_CHAR(SYSDATE, 'YYYYMMDD') AND TO_NUMBER(rej_time) BETWEEN 830 AND 2030) OR -- 夜班:当前时间2030-次日0830,取昨日2030后 + 当日0830前的数据 (TO_NUMBER(TO_CHAR(SYSDATE, 'HH24MI')) > 2030 OR TO_NUMBER(TO_CHAR(SYSDATE, 'HH24MI')) < 830 AND ( (rej_date = TO_CHAR(SYSDATE - 1, 'YYYYMMDD') AND TO_NUMBER(rej_time) > 2030) OR (rej_date = TO_CHAR(SYSDATE, 'YYYYMMDD') AND TO_NUMBER(rej_time) < 830) ))
PL/SQL实现方式(适合存储过程/脚本)
若必须用分支逻辑,需在PL/SQL块中实现,注意处理多行结果的接收:
DECLARE v_current_hhmi NUMBER := TO_NUMBER(TO_CHAR(SYSDATE, 'HH24MI')); -- 若需接收多行结果,需定义游标或集合类型 CURSOR c_shift_data IS SELECT * FROM your_table WHERE CASE WHEN v_current_hhmi BETWEEN 830 AND 2030 THEN rej_date = TO_CHAR(SYSDATE, 'YYYYMMDD') AND TO_NUMBER(rej_time) BETWEEN 830 AND 2030 ELSE (rej_date = TO_CHAR(SYSDATE - 1, 'YYYYMMDD') AND TO_NUMBER(rej_time) > 2030) OR (rej_date = TO_CHAR(SYSDATE, 'YYYYMMDD') AND TO_NUMBER(rej_time) < 830) END; BEGIN -- 循环输出结果示例 FOR rec IN c_shift_data LOOP DBMS_OUTPUT.PUT_LINE('RollID: ' || rec.RollID || ', Reject_Type: ' || rec.Reject_Type); END LOOP; END; /
关键说明
- 用
TO_NUMBER(TO_CHAR(SYSDATE, 'HH24MI'))正确获取当前时间的数字格式时分(如0830转为830,2030转为2030)。 - 夜班条件通过括号明确分组,确保只筛选昨日2030到当日0830的跨天数据。
- 纯SQL写法更简洁高效,适合直接查询;PL/SQL适合需要复杂分支或后续处理的场景。
内容的提问来源于stack exchange,提问作者DeezNuts
相关产品推荐
相关产品推荐

