获取叶级递归选择

时间:2012-04-30 13:25:44

标签: sql postgresql recursive-query

我有一个表格,其中包含id,parent_forum_post_id,对于给定的id = 1221,我发现它是儿童数。

with recursive all_posts (id, parentid, root_id) as (
    select  t1.id,
            t1.parent_forum_post_id as parentid,
            t1.id as root_id
    from    forumposts t1

    union all

    select  c1.id,
            c1.parent_forum_post_id as parentid,
            p.root_id
    from    forumposts c1
    join    all_posts p on p.id = c1.parent_forum_post_id
)
select      (count(*)-1) as child_count
from        all_posts
where       root_id=1221
group by    root_id;

我现在需要的是完全相反的:对于给定的id,找出它的级别,这是由他的父母的数量(它的父级,它的父级的父级,直到它在其父级parent_forum_post_id列中找到null)决定的。希望这是有道理的。

感谢任何帮助。感谢。

3 个答案:

答案 0 :(得分:3)

此查询可以大致简化为:

WITH RECURSIVE p AS (
    SELECT parent_forum_post_id AS p_id
    FROM   forumposts
    WHERE  id = 1221   

    UNION ALL
    SELECT f.parent_forum_post_id
    FROM   p
    JOIN   forumposts f ON f.id = p.p_id
    )
SELECT count(*) AS level
FROM   posts;

也应该快得多。

答案 1 :(得分:2)

WITH recursive
  anticendent
AS
(
  SELECT
    id                       AS post_id,
    parent_forum_post_id     AS anticendent_post_id,
    1                        AS distance
  FROM
    forumposts

  UNION ALL

  SELECT
    anticendent.post_id,
    forumposts.parent_forum_post_id,
    distance + 1
  FROM
    anticendent
  INNER JOIN
    forumposts
      ON forumposts.id = anticendent.anticendent_post_id
)

SELECT
  post_id,
  MAX(distance)  AS level
FROM
  anticendent
GROUP BY
  post_id
WHERE
  post_id = 1221

或者...

SELECT
  *
FROM
  anticendent
WHERE
  post_id = 1221
  AND anticendent_post_id IS NULL

答案 2 :(得分:1)

如果我已经正确理解了你想要特定节点的层次结构深度给定它的id(root是1级)。这是postgresql:

with recursive all_posts (id, parentid, node_id) as (
    select  t1.id,
            t1.parent_forum_post_id as parentid,
            t1.id as node_id
    from    forumposts t1

    union all

    select  c1.id,
            c1.parent_forum_post_id as parentid,
            p.node_id
    from    forumposts c1
    join    all_posts p on p.parentid = c1.id
)
select      count(*) as level
from        all_posts
where       node_id=1221   
group by    node_id;