当前位置: 代码迷 >> Oracle开发 >> oracle日期校验有关问题(求大神帮忙)
  详细解决方案

oracle日期校验有关问题(求大神帮忙)

热度:200   发布时间:2016-04-24 06:24:35.0
oracle日期校验问题(求大神帮忙)
现在有这种情况:有个代理公司跟我司合作,系统需要录入该代理公司的三个证件有效期,且维护代理公司的证件有效期时同一个证件会存在维护多条的情况,且多条的有效期范围之间可能会有空裆日期,如下图:

现在该代理公司与我司签署一份协议,该协议又有一个有效期范围,且系统需要该范围必须在代理公司的三证范围内。
假如我协议的有效期为 :2014-05-01 -- 2016-05-01 这个按理来说是可以签署协议的
 这种校验 我该如何写。

------解决思路----------------------
大神 大神 大神 你在哪里 这里小孩在等你
------解决思路----------------------
拿第一条举个例子。
两条记录,一条是2013-06-01 -- 2014-06-01,另一条是2014-08-01 -- 2016-08-01
协议是2014-05-01 -- 2016-05-01,可不可以签?因为两条记录中有6、7两个月的空白,而协议中包括这两个月。

也就是说:1、是不是就两条记录?2、两条记录之间的日期是连续的?还是可能重叠?还是会有中断?
------解决思路----------------------
引用:

如上图 当我们签署的协议有效期范围为:2014-04-30 -- 2016-05-01 这个系统就需要校验住,提示不能签署协议

你这个例子对么?红框下面那条数据2014/5/2--2018/5/26不是就把你这个2014-04-30 -- 2016-05-01有效期包含了吗?
------解决思路----------------------
引用:
Quote: 引用:

Quote: 引用:


如上图 当我们签署的协议有效期范围为:2014-04-30 -- 2016-05-01 这个系统就需要校验住,提示不能签署协议

你这个例子对么?红框下面那条数据2014/5/2--2018/5/26不是就把你这个2014-04-30 -- 2016-05-01有效期包含了吗?


额 没有啊 我是从4月30号开始的 下面那条是从5月2号开始的

4月30号包含在了第二条数据 2013/5/1-2014/5/1里面了呀 ?其实bussinesstype=1的区间里包含了两个时间段:
2012/5/1--2013/4/29
2013/5/1--2018/5/26
二三条区间可以合并的
------解决思路----------------------
看了几遍,没明白,后来发现应该是1楼的2014年4月30日,应该是2013年才对吧

这有一个解法,就是将该证件的多条记录进行排序,然后前后能连接上的,拼成一条,例如1楼中的图,7515.... 那个证件的3条记录,可以拼成2条,为“2012-5-1 到2013-4-29” 以及 “2013-5-1到2018-5-26” ,签署的时间范围必须在其中一条以内

WITH TAB AS
 (SELECT '0002' BUSINESSNO,
         2 BUSINESSTYPE,
         DATE '2012-1-1' STARTDATE,
         DATE '2018-5-25' ENDDATE,
         79 FILESERIALNO
    FROM DUAL
  UNION ALL
  SELECT '00001', 3, DATE '2012-1-1', DATE '2018-9-19', 79
    FROM DUAL
  UNION ALL
  SELECT '75157623-8', 1, DATE '2012-5-1', DATE '2013-4-29', 79
    FROM DUAL
  UNION ALL
  SELECT '75157623-8', 1, DATE '2013-5-1', DATE '2014-5-1', 79
    FROM DUAL
  UNION ALL
  SELECT '75157623-8', 1, DATE '2014-5-2', DATE '2018-4-29', 79
    FROM DUAL)

--当一个日期范围可以匹配3条记录,即3个证件都在有效期内,则合同可以签署
--这个例子中count为2,不符合条件
SELECT COUNT(1)
  FROM (
        --找出每个证件类型,以及对应的连续区间
        SELECT BUSINESSTYPE, MIN(STARTDATE) STARTDATE, MAX(ENDDATE) ENDDATE
          FROM (SELECT BUSINESSNO,
                        BUSINESSTYPE,
                        STARTDATE,
                        ENDDATE,
                        ROW_NUMBER() OVER(PARTITION BY BUSINESSTYPE ORDER BY STARTDATE) RN,
                        LAG(ENDDATE) OVER(PARTITION BY BUSINESSTYPE ORDER BY STARTDATE) LAG_ENDDATE
                   FROM TAB
                  WHERE FILESERIALNO = 79)
         START WITH LAG_ENDDATE IS NULL
                 OR LAG_ENDDATE < STARTDATE - 1
        CONNECT BY RN = PRIOR RN + 1
               AND LAG_ENDDATE >= STARTDATE - 1
               AND BUSINESSTYPE = PRIOR BUSINESSTYPE
         GROUP BY BUSINESSTYPE, RN - LEVEL)
 WHERE DATE '2013-4-30' >= STARTDATE
   AND DATE '2016-5-1' <= ENDDATE


刚刚写一半有事给忘了。贴上来,提供参考
------解决思路----------------------
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

Quote: 引用:


如上图 当我们签署的协议有效期范围为:2014-04-30 -- 2016-05-01 这个系统就需要校验住,提示不能签署协议

你这个例子对么?红框下面那条数据2014/5/2--2018/5/26不是就把你这个2014-04-30 -- 2016-05-01有效期包含了吗?


额 没有啊 我是从4月30号开始的 下面那条是从5月2号开始的

4月30号包含在了第二条数据 2013/5/1-2014/5/1里面了呀 ?其实bussinesstype=1的区间里包含了两个时间段:
2012/5/1--2013/4/29
2013/5/1--2018/5/26
二三条区间可以合并的


哦  哦 不好意思 我写错了 协议区间应该是2013-04-30 --- 2016-05-01 

select count(distinct bussinesstype) cnt
  from (select level, connect_by_isleaf leaf, connect_by_root(startdate) root,
                a.*
           from 数据表
          start with startdate <= date '2014-4-30'
         connect by startdate = prior enddate + 1
                and bussinesstype = prior bussinesstype)
 where leaf = 1
   and enddate >= date '2016-5-26'

'2014-4-30' 是起始协议日期,'2016-5-26'是结束协议日期
------解决思路----------------------

select count(distinct bussinesstype) cnt
  from (select level, connect_by_isleaf leaf, connect_by_root(startdate) root,
                a.*
           from  数据表  a
          start with startdate <= date '2014-4-30'
         connect by startdate = prior enddate + 1
                and bussinesstype = prior bussinesstype)
 where leaf = 1
   and enddate >= date '2016-5-26'

楼主验证完说一下。
------解决思路----------------------
提供一个我的判断方法,思路:使用给出时间区间落在各有效期的天数之和来判断,如下所述:ab是给出时间区间天数,cc是按bussinesstype综合计算所得的天数,最终结果:若cc=ab则然,否则不然。

with TT as (select '3060' sn,'2' bt,to_date('20120101','yyyymmdd') sd,to_date('20180525','yyyymmdd') ed from dual union all
                   select '3061' sn,'3' bt,to_date('20120101','yyyymmdd') sd,to_date('20180919','yyyymmdd') ed from dual union all
                   select '3177' sn,'1' bt,to_date('20120501','yyyymmdd') sd,to_date('20130429','yyyymmdd') ed from dual union all
                   select '3176' sn,'1' bt,to_date('20130501','yyyymmdd') sd,to_date('20140501','yyyymmdd') ed from dual union all
                   select '3063' sn,'1' bt,to_date('20140502','yyyymmdd') sd,to_date('20180526','yyyymmdd') ed from dual),
T1 as(select sn,bt,greatest(sd - to_date('20130430','yyyymmdd'),0) sa,greatest(sd - to_date('20160501','yyyymmdd'),0) sb,
                    greatest(ed - to_date('20130430','yyyymmdd'),0) ea,greatest(ed - to_date('20160501','yyyymmdd'),0) eb from TT)
select T1.bt,to_date('20160501','yyyymmdd') - to_date('20130430','yyyymmdd') ab,sum(ea-sa-eb)+(select count(*)-1 from T1 s where s.bt=t1.bt and ea-sa-eb>0) cc
  from T1 group by bt order by bt

注:ea-sa-eb即是该记录落在各有效期的天数,而 (select count(*)-1 from T1 s where s.bt=t1.bt and ea-sa-eb>0) 则是分段(有效段)补偿数
  相关解决方案