繁体   English   中英

Postgres自联接递归CTE祖先链

[英]Postgres self-join recursive CTE ancestry chain

我有一个pilates_bill表代表直接祖先(不是树结构)

bill_id (pk) | previous_bill_id (self-join fk)
=============+================================
1               2
2               3
3               4
5               NULL

需要为任何给定的行生成所有祖先的列表(父母/祖父母/祖父母等)(以下示例以1开头)。

使用递归CTE获取具有祖先链的bill_ids列表

WITH RECURSIVE chain(from_id, to_id) AS (
  SELECT NULL::integer, 1  -- starting id
  UNION
  SELECT c.to_id, pilates_bill.previous_bill_id
  FROM chain c
  LEFT OUTER JOIN pilates_bill ON (pilates_bill.bill_id = to_id)
  WHERE c.to_id IS NOT NULL
)
SELECT from_id FROM chain WHERE from_id IS NOT NULL;

结果1,2,3,4,5如预期

但是现在当我尝试按祖先顺序生成表行时,结果就坏了

SELECT * FROM pilates_bill WHERE bill_id IN
(
WITH RECURSIVE chain(from_id, to_id) AS (
  SELECT NULL::integer, 1
  UNION
  SELECT c.to_id, pilates_bill.previous_bill_id
  FROM chain c
  LEFT OUTER JOIN pilates_bill ON (pilates_bill.bill_id = to_id)
  WHERE c.to_id IS NOT NULL
)
SELECT from_id FROM chain WHERE from_id IS NOT NULL
)

行顺序为5,1,2,3,4

我在这里做错了什么?

除非您指定的order by否则SQL查询返回的行的顺序是随机order by

您可以通过在递归CTE中跟踪深度来计算深度:

WITH RECURSIVE chain(from_id, to_id, depth) AS
    (
    SELECT  NULL::integer
    ,       1
    ,       1
    UNION
    SELECT  c.to_id
    ,       pb.previous_bill_id
    ,       depth + 1
    FROM chain c
    LEFT JOIN 
            pilates_bill pb
    ON      pb.bill_id = c.to_id
    WHERE   c.to_id IS NOT NULL
    )
SELECT  * 
FROM    chain
ORDER BY
        depth

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM