sql - 两个日期之间的返回时间,周末除外
问题描述
我需要返回两个日期之间的时间,Oracle
除了周末的时间,我可以返回分钟。但是当我设置周末日期时,我会收到一个null
结果,而不是工作周的剩余时间。
首先,我们需要创建一个函数:
CREATE OR REPLACE FUNCTION get_bus_minutes_between (start_dt DATE, end_dt DATE)
RETURN NUMBER
IS
v_return NUMBER;
BEGIN
select sum(greatest(end_dt - start_dt,0)) * 24 * 60 work_minutes
into v_return
from dual
where trunc(start_dt) - trunc(start_dt,'iw') < 5; -- exclude weekends
RETURN v_return;
END;
案例 1 - 返回工作周中的分钟数 - 好的
在工作周开始和结束。
SELECT
"GET_BUS_MINUTES_BETWEEN"(TO_DATE('14-09-2020 06:00:00', 'dd-mm-yyyy hh24:mi:ss'),
TO_DATE('14-09-2020 10:00:00', 'dd-mm-yyyy hh24:mi:ss')) "WORK_MINUTES"
FROM
"SYS"."DUAL";
案例 2 - 返回工作周的剩余分钟数 - 失败 从周末开始,到工作周结束。
SELECT
"GET_BUS_MINUTES_BETWEEN"(TO_DATE('13-09-2020 06:00:00', 'dd-mm-yyyy hh24:mi:ss'),
TO_DATE('14-09-2020 10:00:00', 'dd-mm-yyyy hh24:mi:ss')) "WORK_MINUTES"
FROM
"SYS"."DUAL";
13-09-2020
是星期天,因此我预计返回时间为与星期一相关的 600 分钟。
在这些可能性中,我们可以从工作日开始,到周末结束。
解决方案
您不需要使用 SQL 或行生成器,只需使用 PL/SQL 进行简单计算即可。改编自我在这里和这里的回答。
CREATE OR REPLACE FUNCTION get_bus_minutes_between (start_dt DATE, end_dt DATE)
RETURN NUMBER
IS
p_start_date DATE;
p_end_date DATE;
p_working_days NUMBER;
BEGIN
IF start_dt IS NULL OR end_dt IS NULL THEN
RETURN NUll;
END IF;
-- Enforce that the values are earliest start date to latest end date.
p_start_date := LEAST( start_dt, end_dt );
p_end_date := GREATEST( start_dt, end_dt );
-- Calculate the number of days from the beginning of the ISO week containing
-- the start date and the beginning of the ISO week containing the end date
-- and then multiply this by 5/7 to get the number of full business days.
--
-- Then add on the extra days from the beginining of the ISO week containing
-- the end date and the end date and subtract the extra days from the
-- beginning of the ISO week containing the start date to the start date.
p_working_days := ( TRUNC( p_end_date, 'IW' ) - TRUNC( p_start_date, 'IW' ) ) * 5 / 7
+ LEAST( p_end_date - TRUNC( p_end_date, 'IW' ), 5 )
- LEAST( p_start_date - TRUNC( p_start_date, 'IW' ), 5 );
-- If the start date and end date are reversed then return a negative value.
IF start_dt > end_dt THEN
RETURN -ROUND( p_working_days * 24 * 60, 3 );
ELSE
RETURN +ROUND( p_working_days * 24 * 60, 3 );
END IF;
END;
/
然后:
SELECT GET_BUS_MINUTES_BETWEEN(
DATE '2020-09-14' + INTERVAL '6' HOUR,
DATE '2020-09-14' + INTERVAL '10' HOUR
) AS minutes_between
FROM DUAL;
输出:
| MINUTES_BETWEEN | | --------------: | | 240 |
和:
SELECT GET_BUS_MINUTES_BETWEEN(
DATE '2020-09-13' + INTERVAL '6' HOUR,
DATE '2020-09-14' + INTERVAL '10' HOUR
) AS minutes_between
FROM DUAL;
输出:
| MINUTES_BETWEEN | | --------------: | | 600 |
db<>在这里摆弄
推荐阅读
- javascript - Node.js paypal rest api error401
- nestjs - Nestjs 全局缓存:CacheInterceptor 问题
- python - 数据框字典上的python groupby
- sip - 如何从 pjsua2 中的 SDP 正文获取媒体属性?
- javascript - 通过 JSON 响应解析 - React Native
- firebase - Firebase 规则 - 用户只能编辑其数据
- scala - 如何使用scala在镶木地板文件中写入常量值?
- wordpress - 如何根据子域的 ID 显示 WordPress 帖子
- sql - 如何在同一查询中使用 rowNumber 获取 MAX rownumber
- javascript - 如何在递归方法中进行同步调用?