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"
我正在处理从层次结构中提取数据的查询
例如
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"