【问题标题】:Find all descendants with recursive CTE使用递归 CTE 查找所有后代
【发布时间】:2017-10-19 08:58:43
【问题描述】:

我有一个这样的 postgres 数据库,其中包含表 ids

  id INT PRIMARY KEY, 
  value TEXT,
  parent_id INT REFERENCES ids DEFAULT NULL

我想查找此表中所有行的后代数量。因此,对于树中的所有叶子,子树的大小将为 1。

我想用递归 CTE 做到这一点并写了这个:

WITH RECURSIVE r AS (
SELECT id, parent_id
from keyword
where id=1

UNION 

SELECT k.id, k.parent_id
FROM keyword k
join r on k.parent_id = r.id)

select count(*) from r;

我只能计算某个 id 的后代,而不是全部。我试图在 CTE 中按 id 编写 group,但它不起作用(大多数情况下它为所有顶点提供等于 1 的子树大小)。

根据这张表,

 id | parent_id | value  
 ----+-----------+--------
  1 |           | SELECT
  2 |         1 | FROM
  3 |         1 | WHERE
  4 |         1 | ORDER
  5 |         4 | BY
  6 |         1 | GROUP
  7 |         6 | BY
  8 |         6 | HAVING
 11 |           | UPDATE
 12 |        11 | SET
 13 |        11 | WHERE

我想得到那个:

 id | subtree_size
-------+----------
 1 | 11
 2 | 1
 6 | 3...

对于树中的所有 id。

【问题讨论】:

  • 所有树:从所有根开始:where id=1 -->> where parent_id IS NULL 您可以在结果中保留根并在外部查询中对其进行分组。
  • 更正:id=1 的 subtree_size 为 8。({11,12,13} 在单独的树中)

标签: postgresql recursion common-table-expression


【解决方案1】:
CREATE TABLE keyword
        ( id INTEGER PRIMARY KEY
        , parent_id INT REFERENCES keyword(id) DEFAULT NULL
        , value TEXT
        );
INSERT INTO keyword(id,parent_id, value) VALUES
 ( 1, NULL, 'SELECT')
,( 2, 1, 'FROM')
,( 3, 1, 'WHERE')
,( 4, 1, 'ORDER')
,( 5, 4, 'BY')
,( 6, 1, 'GROUP')
,( 7, 6, 'BY')
,( 8, 6, 'HAVING')
,( 11, NULL, 'UPDATE')
,( 12, 11, 'SET')
,( 13, 11, 'WHERE')
        ;


WITH RECURSIVE r AS (
        SELECT id AS root -- <<== 'Anchor' the root
        , id, parent_id
        from keyword
        -- where id=1
        -- where parent_id IS NULL
        WHERE id IN (1,2,6) -- <<== UPDATE
UNION
        SELECT r.root   -- <<== This is the trick: maintain the parent's root
        , k.id, k.parent_id
        FROM keyword k
        join r on k.parent_id = r.id
        )
select distinct k.value, r.root, count(*) AS cnt
from r
JOIN keyword k ON k.id = r.root
GROUP BY r.root, k.value
        ;

【讨论】:

  • 它实际上计算了整个树中根顶点的后代数量,因为 r.root 将始终是根顶点的 id。我需要遍历所有节点并计算后代,因为它们每个都是根。
  • 如果只有一个根,显然只有一组和一个聚合。 (你的问题在这方面不是很清楚)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-19
  • 2011-10-02
  • 2011-04-25
  • 2020-07-27
  • 2014-08-11
相关资源
最近更新 更多