Oracle with的重复使用(递归)

Oracle with的重复使用(递归)

写力扣的时候学到了新的方法 Recursive WITH Clauses

通常来说如果直接使用with XXX as ()这种,是没发直接使用自身的数据的

例如

/* Write your PL/SQL query statement below */
with maina as ( 
    select distinct p.post_id,k.topic_id
    from Posts p left join Keywords k
     on 
    instr(lower(' '||p.content||' '), lower(' '||k.word||' ')) > 0 order by p.post_id,k.topic_id
),
mainb as (
    select b.post_id,listagg(nvl(b.topic_id,'999'),',') within group(order by b.topic_id) as list from maina b group by b.post_id
)

select c.post_id,decode(c.list,'999','Ambiguous!',c.list) as topic from mainb c 

但是如果将格式换成 with table_name(XX,XX,XX,XX,XX) as ()

就可以在with的代码段中直接调用自己的结果,效果和常用的递归手段,如CONNECT_BY_ROOT是差不多的,比connect by prior多分层

例如(直接用别人的sql了)

with bus_store(bus_id,capacity,cnt,arrival_time,rn) as (
    select c.* 
    from 
    (
        select bus_id, capacity, count(b.passenger_id) cnt,a.arrival_time,
        row_number() over(order by a.arrival_time) rn 
        from 
        (
            select bus_id,capacity,arrival_time 
            from Buses
        ) a  left join Passengers b 
        on(b.arrival_time<=a.arrival_time)
        group by bus_id,capacity,a.arrival_time
    ) c
),
result(bus_id,cnt,diff,passengers_cnt,arrival_time,rn) as (
    select bus_id,cnt,
    case when capacity >= cnt then 0 else cnt-capacity end,
    case when capacity >= cnt then cnt else capacity end,
    arrival_time,rn 
    from bus_store
    where rn=1
    union  all 
    select a.bus_id,a.cnt,
    case when a.cnt - b.cnt + b.diff >= a.capacity then a.cnt - b.cnt + b.diff - a.capacity else 0 end,
    case when a.cnt - b.cnt + b.diff >= a.capacity then a.capacity else a.cnt - b.cnt + b.diff end,
    a.arrival_time,a.rn 
    from bus_store a join result b 
    on(a.arrival_time > b.arrival_time) 
    where a.rn = b.rn + 1
)

select bus_id,passengers_cnt from result order by bus_id
posted @ 2023-03-12 13:37  DbWong_0918  阅读(275)  评论(0编辑  收藏  举报