Postgres Group链接列表查询

时间:2016-08-01 21:11:47

标签: postgresql common-table-expression recursive-query

我想将对象Foo分组,该对象具有属性leftright,可以为null或包含另一个pid的{​​{1}}对象

我想要一种方法来组合通过查询按组链接在一起的所有对象。每个组的ID可以是随机的,但必须是不同的。

示例输入

Foo

输出:

╔═════╦══════════╦════╦════╦
║ FO  ║ left     ║  right  ║
╠═════╬══════════╬═════════╬
║  1  ║     3    ║   2     ║
║  2  ║     1    ║         ║
║  3  ║          ║   1     ║
║  4  ║     5    ║   6     ║
║  5  ║          ║   4     ║
║  6  ║     4    ║         ║
╚═════╩══════════╩════╩════╩

2 个答案:

答案 0 :(得分:2)

递归数据结构需要递归查询。示例数据:

create table foo(id int, lt int, rt int);
insert into foo values
(1, 3, 2),
(2, 1, null),
(3, null, 1),
(4, 5, 6),
(5, null, 4),
(6, 4, null);

查询:

with recursive find (id, lt, rt, ids) as (
    select id, lt, rt, array[id]
    from foo
union all
    select 
        r.id, f.lt, f.rt, 
        case when ids[1] < f.id then ids || f.id else f.id || ids end
    from find r
    join foo f on f.id = r.lt or f.id = r.rt
    where f.id <> all(ids)
    )
select distinct on (id) id, ids[1] as group
from find
order by id, array_length(ids, 1) desc;

 id | group 
----+-------
  1 |     1
  2 |     1
  3 |     1
  4 |     4
  5 |     4
  6 |     4
(6 rows)    

组的ID不是随机的,它是元素的最小(id)。

答案 1 :(得分:1)

从@klin修改

create table public.foo (
id numeric,
lt numeric,
rt numeric
);

insert into public.foo values
(1,3,2), (2,1,null), (3,null,1), 
(4,5,6), (5,null,4), (6,4,null);

with recursive find (id, lt, rt, grp) as (
    select 
        id, lt, rt, 
        id -- rightmost id for grouping
    from public.foo
    where rt is null -- Get the rightmost objects
    union all
    select 
        r.id, r.lt, r.rt, 
        grp -- kept constant from rightmost object on the list
    from public.foo r
    join find f on r.id = f.lt -- Traverse list from right to left
    -- Recursion will stop when all left ids are null
    )
select id, grp from find
order by grp, id;
  • 拿最右边的物体。
  • 从右到左遍历。
  • 最右边id保持不变以进行分组