Oracle递归查询Sql日期之间的3个月差

时间:2019-05-10 09:01:49

标签: sql oracle

我有一个简单的表,其中包含三列,即policy_no,casenumber和created_date。可以对照唯一的策略号记录多个案例号。我需要一个查询,该查询遍历数据以查找最早的策略案例,然后检查该策略与下一个策略之间的区别。如果差异大于三个月,则包括第一个案例,如果差异较小,则排除第一个案例,然后转到第二个案例,然后再次检查该案例与第三个案例之间的差异。基本上,我只想包括在接下来的三个月内没有提出其他案件的案件。

Select * from policy_table
where policy_no = '17850850'

将返回以下结果;

policy_no   casenumber  created_date
17850850    4150778     16-APR-19
17850850    3955549     22-JAN-19
17850850    3188447     14-MAY-18
17850850    2998931     14-MAR-18
17850850    2767545     29-DEC-17
17850850    2420594     05-SEP-17

应该包括2017年5月9日提出的第一起案件,因为直到2017年12月29日(超过3个月)才提出进一步的案件。 2017年12月29日提出的案件应排除在外,因为该案件是在2018年3月14日提出的。在14/03/2018提出的案件也应排除在外,因为另一案件在14/05/2018(在3个月内)提出。应该包括在14/05/2018提出的案件,应该在22/01/2019排除在外,并且应该暂时包括16/04/2019(但在接下来的三个月内不会再提出任何案件)。任何帮助将非常感激。希望能做到这一点;

policy_no   casenumber  created_date    Diff    Outcome
17850850    4150778     16-APR-19               latest
17850850    3955549     22-JAN-19       2.8     excluded
17850850    3188447     14-MAY-18       8.3     Included
17850850    2998931     14-MAR-18       2       excluded
17850850    2767545     29-DEC-17       2.5     excluded
17850850    2420594     05-SEP-17       3.77    Included

2 个答案:

答案 0 :(得分:2)

您无需递归执行此操作,可以使用not exists检查三个月内是否有任何情况:

-- CTE for sample data
with your_table (policy_no, casenumber, created_date) as (
            select 17850850, 4150778, date '2019-04-16' from dual
  union all select 17850850, 3955549, date '2019-01-22' from dual
  union all select 17850850, 3188447, date '2018-05-14' from dual
  union all select 17850850, 2998931, date '2018-03-14' from dual
  union all select 17850850, 2767545, date '2017-12-29' from dual
  union all select 17850850, 2420594, date '2017-09-17' from dual
)
-- actual query
select policy_no, casenumber, created_date
from your_table t
where policy_no = 17850850
and not exists (
  select *
  from your_table t2
  where t2.policy_no = t.policy_no
  and t2.casenumber != t.casenumber
  and t2.created_date >= t.created_date
  and t2.created_date <= add_months(t.created_date, 3)
)
order by policy_no, created_date desc;

 POLICY_NO CASENUMBER CREATED_DATE
---------- ---------- ------------
  17850850    4150778 2019-04-16  
  17850850    3188447 2018-05-14  
  17850850    2420594 2017-09-17  

如果您想查看所有带有基于月份的差异和最新/排除/包含的标志的行(如已编辑的问题所示),则可以使用内联视图查找下一个创建的日期和差异,然后根据外部查询中的标记得出标记:

-- with same CTE for sample data
select policy_no, casenumber, created_date,
  trunc(diff, 2) as diff,
  case when diff is null then 'latest'
       when diff <= 3 then 'excluded'
       else 'included'
  end as outcome
from (
  select policy_no, casenumber, created_date,
    months_between(lead(created_date) over (partition by policy_no order by created_date),
      created_date) as diff
  from your_table t
)
where policy_no = 17850850
order by policy_no, created_date desc;

 POLICY_NO CASENUMBER CREATED_DATE       DIFF OUTCOME 
---------- ---------- ------------ ---------- --------
  17850850    4150778 2019-04-16              latest  
  17850850    3955549 2019-01-22          2.8 excluded
  17850850    3188447 2018-05-14         8.25 included
  17850850    2998931 2018-03-14            2 excluded
  17850850    2767545 2017-12-29         2.51 excluded
  17850850    2420594 2017-09-17         3.38 included

您可以使用相同的内联视图方法来仅获取包含的行:

-- with same CTE
select policy_no, casenumber, created_date
from (
  select policy_no, casenumber, created_date,
    months_between(lead(created_date) over (partition by policy_no order by created_date),
      created_date) as diff
  from your_table t
)
where policy_no = 17850850
and (diff is null or diff > 3)
order by policy_no, created_date desc;

 POLICY_NO CASENUMBER CREATED_DATE
---------- ---------- ------------
  17850850    4150778 2019-04-16  
  17850850    3188447 2018-05-14  
  17850850    2420594 2017-09-17  

db<>fiddle

答案 1 :(得分:1)

使用LAG分析函数和MONTHS_BETWEEN

Oracle设置

CREATE TABLE test_data ( policy_no, casenumber, created_date ) AS
SELECT 17850850, 4150778, DATE '2019-04-16' FROM DUAL UNION ALL
SELECT 17850850, 3955549, DATE '2019-01-22' FROM DUAL UNION ALL
SELECT 17850850, 3188447, DATE '2018-05-14' FROM DUAL UNION ALL
SELECT 17850850, 2998931, DATE '2018-03-14' FROM DUAL UNION ALL
SELECT 17850850, 2767545, DATE '2017-12-29' FROM DUAL UNION ALL
SELECT 17850850, 2420594, DATE '2017-09-05' FROM DUAL

查询

SELECT t.*,
       CASE
       WHEN diff IS NULL THEN 'latest'
       WHEN diff <= 3    THEN 'excluded'
                         ELSE 'included'
       END AS outcome
FROM (
  SELECT t.*,
         MONTHS_BETWEEN(
           LAG( created_date ) OVER ( PARTITION BY policy_no ORDER BY created_date DESC ),
           created_date
         ) AS diff
  FROM   test_data t
) t

输出

POLICY_NO | CASENUMBER | CREATED_DATE |                                     DIFF | OUTCOME 
--------: | ---------: | :----------- | ---------------------------------------: | :-------
 17850850 |    4150778 | 16-APR-19    |                                     null | latest  
 17850850 |    3955549 | 22-JAN-19    | 2.80645161290322580645161290322580645161 | excluded
 17850850 |    3188447 | 14-MAY-18    | 8.25806451612903225806451612903225806452 | included
 17850850 |    2998931 | 14-MAR-18    |                                        2 | excluded
 17850850 |    2767545 | 29-DEC-17    | 2.51612903225806451612903225806451612903 | excluded
 17850850 |    2420594 | 05-SEP-17    | 3.77419354838709677419354838709677419355 | included

db <>提琴here