查找包含某些id Postgres的所有数组

时间:2017-10-19 17:55:23

标签: postgresql common-table-expression

我将邻接树存储在表中。我编写了一个递归的Common Table表达式来查找树中每个节点的所有优先级。 所以当我写SELECT * FROM TREE;

我明白了:

 id |   ancestors   
----+---------------
  0 | {} <- ROOT
  1 | {0}
  2 | {0}
  4 | {0}
 19 | {0}
 45 | {0}
  3 | {0,1}
  5 | {0,4}
  6 | {0,4}
  8 | {0,4}
 11 | {0,1}
 22 | {0,2}
  7 | {0,4,5}
  9 | {0,4,6}

我想得到树中每个节点的所有后代的数量,所以对于每个唯一的id,我想在祖先列中找到包含这样的id的数组。

我可以手动完成,但只能用于一个ID:

SELECT count(*) from tree
WHERE 0 = any(tree.ancestors);

对于此查询,如果id = 0的节点是根节点,它应该给我树中所有节点的数量减1。

我试着写这样的东西:

SELECT count(*) from tree
WHERE id = any(tree.ancestors)
group by id;

但它实际上返回0行。

1 个答案:

答案 0 :(得分:1)

您想要搜索每个id的整个树,这是一个带条件的自连接:

with tree(id, ancestors) as (
values
    (0, '{}'::int[]),
    (1, '{0}'),
    (2, '{0}'),
    (4, '{0}'),
    (19, '{0}'),
    (45, '{0}'),
    (3, '{0,1}'),
    (5, '{0,4}'),
    (6, '{0,4}'),
    (8, '{0,4}'),
    (11, '{0,1}'),
    (22, '{0,2}'),
    (7, '{0,4,5}'),
    (9, '{0,4,6}')
)

select t1.id, count(t2.*)
from tree t1
join tree t2 on t1.id = any(t2.ancestors)
group by 1
order by 1

 id | count 
----+-------
  0 |    13
  1 |     2
  2 |     1
  4 |     5
  5 |     1
  6 |     1
(6 rows)

请注意,如果您想要获取所有left joinids中未显示的内容),则应使用ancestors