仅一列的Oracle递归查询

时间:2018-06-27 22:43:13

标签: oracle recursion

我有一个表leg和一个日期列datainizio,其中有行:

23-MAR-18
15-MAR-13

我必须确认外部日期在sysdate和18-mar-18或22-mar-18和15-mar-13之间。这些日期来自表par,具有:

02-APR-18
04-MAR-17
17-MAR-16

我想要得到的结果:

range                   count
----------------------  -----
23-MAR-18 - sysdate         1
15-MAR-13 - 22-MAR-18       2

是否可以通过递归做到这一点?

1 个答案:

答案 0 :(得分:0)

您可以使用Lead函数生成范围:

select datainizio as date_from,
  coalesce(lead(datainizio) over (order by datainizio), sysdate) as date_to
from leg;

DATE_FROM  DATE_TO   
---------- ----------
2013-03-15 2018-03-23
2018-03-23 2018-06-28

,然后将其视为CTE,并使用左外部联接到par表以根据范围对匹配进行计数:

with ranges as (
  select datainizio as date_from,
    coalesce(lead(datainizio) over (order by datainizio), sysdate) as date_to
  from leg
)
select r.date_from, r.date_to - 1/86400 as date_to, count(p.datainizio)
from ranges r
left join par p
on p.datainizio >= r.date_from
and p.datainizio < r.date_to
group by r.date_from, r.date_to
order by r.date_from;

DATE_FROM  DATE_TO    COUNT(P.DATAINIZIO)
---------- ---------- -------------------
2013-03-15 2018-03-22                   2
2018-03-23 2018-06-28                   1

我正在将date-to值调回一秒,以获取前一天的值(sysdate除外)。如果par日期的所有时间都是午夜,那么您可以改为在CTE中进行,在那儿休息一天。 (这也假定它将在今天午夜之后运行。)

如果您希望将显示的范围显示为字符串,并以sysdate作为单词,则可以稍微修改CTE并使用字符串连接:

with ranges as (
  select datainizio as date_from,
    lead(datainizio) over (order by datainizio) as date_to
  from leg
)
select to_char(r.date_from, 'DD-MON-RR') || ' - ' ||
  case when date_to is null then 'sysdate'
       else to_char(date_to - 1/86400, 'DD-MON-RR')
  end as range,
  count(p.datainizio)
from ranges r
left join par p
on p.datainizio >= r.date_from
and p.datainizio < coalesce(r.date_to, sysdate)
group by r.date_from, r.date_to
order by r.date_from;

RANGE                 COUNT(P.DATAINIZIO)
--------------------- -------------------
15-MAR-13 - 22-MAR-18                   2
23-MAR-18 - sysdate                     1

db<>fiddle demo.