Postgresql 递归 CTE 结果排序

Postgresql recursive CTE results ordering

我正在处理从层次结构中提取数据的查询

例如

CREATE table org (
   id   INT PRIMARY KEY,
   name TEXT NOT NULL,
   parent_id INT);

INSERT INTO org (id, name) VALUES (0, 'top');
INSERT INTO org (id, name, parent_id) VALUES (1, 'middle1', 0);
INSERT INTO org (id, name, parent_id) VALUES (2, 'middle2', 0);
INSERT INTO org (id, name, parent_id) VALUES (3, 'bottom3', 1);

WITH RECURSIVE parent_org (id, parent_id, name) AS (
  SELECT id, parent_id, name
  FROM org
  WHERE id = 3
UNION ALL
    SELECT o.id, o.parent_id, o.name
    FROM   org o, parent_org po
    WHERE  po.parent_id = o.id)
SELECT id, parent_id, name
FROM parent_org;

它按预期工作。

3 1 "bottom3"
1 0 "middle1"
0   "top"

它也按照我期望的顺序返回数据,我认为这样做是有意义的,因为结果会被发现。

问题是,我可以指望这样的订单吗?

是的,有一个定义的顺序。在Postgres WITH doc中,他们举了下面的例子:

WITH RECURSIVE search_graph(id, link, data, depth, path, cycle) AS (
        SELECT g.id, g.link, g.data, 1,
          ARRAY[ROW(g.f1, g.f2)],
          false
        FROM graph g
      UNION ALL
        SELECT g.id, g.link, g.data, sg.depth + 1,
          path || ROW(g.f1, g.f2),
          ROW(g.f1, g.f2) = ANY(path)
        FROM graph g, search_graph sg
        WHERE g.id = sg.link AND NOT cycle
)
SELECT * FROM search_graph;

他们在 提示 框(格式化我的)中说:

The recursive query evaluation algorithm produces its output in breadth-first search order. You can display the results in depth-first search order by making the outer query ORDER BY a "path" column constructed in this way.

根据 INSERT 语句,在你上面的案例中,你似乎确实得到了 广度优先 输出,所以我想说你可以,如果你愿意的话,修改您的外部 SELECT 以另一种方式订购它。

我相信在你的情况下 depth-first 的模拟可能是这样的:

WITH RECURSIVE parent_org (id, parent_id, name) AS (
  SELECT id, parent_id, name
  FROM org
  WHERE id = 3
UNION ALL
    SELECT o.id, o.parent_id, o.name
    FROM   org o, parent_org po
    WHERE  po.parent_id = o.id)
SELECT id, parent_id, name
FROM parent_org
ORDER BY id;

正如我所期望的(运行 我脑子里的事情)会产生这个:

0   "top"
1 0 "middle1"
3 1 "bottom3"