sqlite3递归聚合数据

时间:2017-04-02 19:15:56

标签: recursion sqlite aggregate

这可能是一种背包问题。 我需要遍历数据表,按列分组,选择时间更长的数据表。 然后重复上一步,直到达不到CAPACITY列给出的限制。

这是演示场景:

create table if not exists data( vid num, size num, epid num, sid num, capacity num, dt );
    delete from data;
    insert into data(vid,size,epid,sid,capacity,dt)
    values
        (0,20,1,1,50,1100), -- 2nd choice
        (0,20,1,1,50,1000), -- 1st choice
        (0,20,1,1,50,1200), -- last choice excluded because out of capacity
        (1,20,2,2,50,1100), -- 2nd choice
        (1,20,2,2,50,1000), -- 1st choice
        (1,20,2,2,50,1200); -- last choice excluded because out of capacity

这是非递归解决方案:

with best0 as (
    select a.rowid as tid,a.vid,a.sid,a.size,a.dt,a.capacity-a.size as remains,0 as level 
    from data a 
    group by a.sid 
    having min(a.dt)
    ),
best1 as (
    select a.tid,a.vid,a.sid,a.size,a.dt,a.remains, a.level 
    from (
        select 
            a.rowid as tid,a.sid,a.vid,a.size,a.capacity,a.dt,b.remains-a.size as remains,
            b.level+1 as level 
        from data a 
        join best0 b on b.sid=a.sid -- and b.level=a.level-1
        where not a.rowid in (select tid from best0) 
          and b.remains-a.size>0
        ) a group by a.sid having min(a.dt)
    ),
best2 as (
    select a.tid,a.vid,a.sid,a.size,a.dt,a.remains, a.level 
    from (
        select 
            a.rowid as tid,a.sid,a.vid,a.size,a.capacity,a.dt,b.remains-a.size as remains,
            b.level+1 as level 
        from data a 
        join best1 b on b.sid=a.sid -- and b.level=a.level-1
        where not a.rowid in (select tid from best0 union all select tid from best1) 
          and b.remains-a.size>0
        ) a group by a.sid having min(a.dt)
    )
select * from best0
union all
select * from best1
union all
select * from best2

这就是结果:

tid | vid | sid | size | Dtime | capacity | group_level
--- | --- | --- | ---- | ----- | -------- | -----------
2   | 0   | 1   | 20   | 1000  | 30       | 0
5   | 1   | 2   | 20   | 1000  | 30       | 0
1   | 0   | 1   | 20   | 1100  | 10       | 1
4   | 1   | 2   | 20   | 1100  | 10       | 1

这是给出错误的递归版本:"子查询中的递归引用:best"

with recursive best(tid,vid,sid,size,dt,remains,level) 
as (
    select a.rowid as tid,a.vid,a.sid,a.size,a.dt,a.capacity-a.size as remains,0 as level 
    from data a 
    group by a.sid 
    having min(a.dt)

    union all

    select a.tid,a.vid,a.sid,a.size,a.dt,a.remains, a.level 
    from (
        select 
            a.rowid as tid,a.sid,a.vid,a.size,a.dt,b.remains-a.size as remains,
            b.level+1 as level 
        from data a 
        join best b on b.sid=a.sid -- and b.level=a.level-1
        where not a.rowid in (select tid from best) and b.remains-a.size>0
        ) a group by a.sid having min(a.dt)
    )
select * from best

我甚至使用循环计数器尝试过不同的解决方案,但每个人都会犯同样的错误。

0 个答案:

没有答案