oracle 计算时间差,排除非工作时间 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nutting

oracle 计算时间差,排除非工作时间

  •  
  •   nutting 2018 年 6 月 1 日 3044 次点击
    这是一个创建于 2881 天前的主题,其中的信息可能已经有所发展或是发生改变。

    要求只计算 8-12,14-18,我现在 csdn 找见有人探讨写的算法,结果仔细一侧,有些临界的地方就算不对了,比如 17:50 到第二天 8:10,算出来不是 20 分钟,好复杂啊,就只用 oracle 的话到底怎么能写对?

    create or replace function wk_minutes_between( i_startTime varchar2, -- 起始时间:( 格式:'YYYY-MM-DD HH24:MI:SS' ) i_endTime varchar2 -- 结束时间:( 格式:'YYYY-MM-DD HH24:MI:SS' ) ) return number is v_real_startTime date; v_real_endTime date; v_hours number(18,0); v_number number(18,4); begin v_real_startTime := to_date(i_startTime,'YYYY-MM-DD HH24:MI:SS'); v_real_endTime := to_date(i_endTime,'YYYY-MM-DD HH24:MI:SS'); if v_real_startTime > v_real_endTime -- 如果起始时间大于结束时间,将起始时间与结束时间替换 then select v_real_startTime, v_real_endTime into v_real_endTime, v_real_startTime from dual; end if; if v_real_startTime > v_real_endTime -- 如果起始时间大于结束时间,将起始时间与结束时间替换 then select v_real_startTime, v_real_endTime into v_real_endTime, v_real_startTime from dual; end if; if v_real_startTime<trunc(v_real_startTime,'dd')+8/24 -- 如果小于当天 8 点,将其置为当天 8 天(因为你是 8 点上班) then v_real_startTime:=trunc(v_real_startTime,'dd')+8/24; -- 如果大于当天 12 点,且小于当天 14 点,将其置为当天 14 点(因为你下午是 14 点上班) elsif v_real_startTime>trunc(v_real_startTime,'dd')+12/24 and v_real_startTime<trunc(v_real_startTime,'dd')+14/24 then v_real_startTime:=trunc(v_real_startTime,'dd')+14/24; -- 如果大于当天 18 点,将其置为第二天 8 天 elsif v_real_startTime>trunc(v_real_startTime,'dd')+18/24 then v_real_startTime:=trunc(v_real_startTime+1,'dd')+8/24; end if; -- 如果小于当天 8 点,将其置为昨天 18 点 if v_real_endTime<trunc(v_real_endTime,'dd')+8/24 then v_real_endTime:=trunc(v_real_endTime-1,'dd')+18/24; -- 如果大于当天 12 点,且小于当天 14 点,将其置为当天 12 点(因为你上午是 12 点下班) elsif v_real_endTime>trunc(v_real_endTime,'dd')+12/24 and v_real_endTime<trunc(v_real_endTime,'dd')+14/24 then v_real_endTime:=trunc(v_real_endTime,'dd')+12/24; elsif v_real_endTime>trunc(v_real_endTime,'dd')+18/24 -- 如果大于当天 18 点,将其置为当天 18 天(因为你是 18 点下班) then v_real_endTime:=trunc(v_real_endTime,'dd')+18/24; end if; with a as( select v_real_startTime+(level-1)/24 as cdate, trunc(v_real_startTime+(level-1)/24,'hh') as tr_cdate from dual connect by level <= (v_real_endTime-v_real_startTime)*24+2 ), b as( select cdate, tr_cdate cdate2 from a /*where trunc(a.cdate) not in (select hdate from holidays) and to_char(a.cdate,'D') not in ('1','7')*/ ), -- 排除周六、日 和 节假日 c as( select (case when to_char(t1.cdate,'hh24') in ('12','18') then trunc(t1.cdate,'hh') else t1.cdate end) as cdate1, (case when to_char(t2.cdate,'hh24') in ('14') then trunc(t2.cdate,'hh') else t2.cdate end) as cdate2 from b t1 left join b t2 on trunc(t1.cdate,'hh24')=trunc(t2.cdate+1/24,'hh24') order by (case when to_char(t1.cdate,'h') in ('08','12','14','18') then trunc(t1.cdate,'hh') else t1.cdate end) ), d as ( select (case when c.cdate1>v_real_endTime then v_real_endTime else c.cdate1 end) as cdate1, c.cdate2 from c where to_char(c.cdate1,'hh24') in ('09','10','11','12','15','16','17','18') ) select sum(d.cdate1-nvl(d.cdate2,d.cdate1))*24 into v_number from d; return v_number; end; 测试: --这样算,480 分钟,正好是 8 个小时,说明算法基本没问题 select wk_minutes_between('2018-05-21 07:50:00','2018-05-21 18:10:00')*60 from dual; --下面这个就不对了,只算出来是 10 分钟 select wk_minutes_between('2018-05-21 17:50:00','2018-05-22 08:10:00')*60 from dual; 
    1 条回复    2018-06-02 08:50:33 +08:00
    nutting
        1
    nutting  
    OP
       2018 年 6 月 2 日
    没人感兴趣?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5604 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 08:57 PVG 16:57 LAX 01:57 JFK 04:57
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86