Oracle SQL中日期相加如何排除周末实现工作日偏移计算?
工作日日期偏移实现方案
核心逻辑
你当前使用的to_date('2021-01-05', 'yyyy-mm-dd')+15是直接计算自然日偏移,要排除周末的本质是计算N个工作日后的日期,需要在遍历日期时自动跳过周六、周日两天。
各数据库常用实现方式
Oracle(你当前用的to_date为Oracle原生语法)
可以用CONNECT BY递归生成待遍历的日期序列,过滤掉周末后取第15个有效日期即可:
SELECT dt FROM ( SELECT to_date('2021-01-05', 'yyyy-mm-dd') + LEVEL AS dt, ROW_NUMBER() OVER(ORDER BY LEVEL) AS rn FROM DUAL WHERE TO_CHAR(to_date('2021-01-05', 'yyyy-mm-dd') + LEVEL, 'DY', 'NLS_DATE_LANGUAGE=AMERICAN') NOT IN ('SAT', 'SUN') CONNECT BY LEVEL <= 30 -- 预留足够自然日范围,15个工作日最多仅需21个自然日即可覆盖 ) WHERE rn = 15;
注:如果使用Oracle 11g及以上企业版,也可以直接调用内置工作日计算函数
WORKDAY_ADD,写法更简洁:SELECT WORKDAY_ADD(to_date('2021-01-05', 'yyyy-mm-dd'),15) FROM DUAL;
MySQL 8.0+
用递归CTE实现逻辑一致的计算:
WITH RECURSIVE workdays AS ( SELECT '2021-01-05' AS dt, 0 AS day_count UNION ALL SELECT dt + INTERVAL 1 DAY, CASE WHEN WEEKDAY(dt + INTERVAL 1 DAY) < 5 THEN day_count + 1 ELSE day_count END FROM workdays WHERE day_count < 15 ) SELECT MAX(dt) FROM workdays;
PostgreSQL
可直接用递归CTE实现:
WITH RECURSIVE workdays AS ( SELECT '2021-01-05'::date AS dt, 0 AS cnt UNION ALL SELECT dt + 1, CASE WHEN EXTRACT(DOW FROM dt + 1) NOT IN (0,6) THEN cnt + 1 ELSE cnt END FROM workdays WHERE cnt < 15 ) SELECT max(dt) FROM workdays;
内容的提问来源于stack exchange,提问作者wjack_backsstreeu
相关产品推荐
相关产品推荐

