Joh*_*and 14 postgresql cte order-by recursive
假设您有这样的nodes表:
CREATE TABLE nodes
(
node serial PRIMARY KEY,
parent integer NULL REFERENCES nodes(node),
ts timestamp NOT NULL DEFAULT now()
);
Run Code Online (Sandbox Code Playgroud)
它代表了一个标准的类似节点的树结构,根节点在顶部,几个子节点悬挂在根节点或其他子节点上。
让我们插入几个示例值:
INSERT INTO nodes (parent)
VALUES (NULL), (NULL), (NULL), (NULL), (1), (1), (1), (1), (6), (1)
, (6), (9), (6), (6), (3), (3), (3), (15);
Run Code Online (Sandbox Code Playgroud)
现在我想检索前 10 个根节点及其所有子节点,深度为 4:
WITH RECURSIVE node_rec AS
(
(SELECT 1 AS depth, * FROM nodes WHERE parent IS NULL LIMIT 10)
UNION ALL
SELECT depth + 1, n.*
FROM nodes AS n JOIN node_rec ON (n.parent = node_rec.node)
WHERE depth < 4
)
SELECT * FROM node_rec;
Run Code Online (Sandbox Code Playgroud)
这很好用,并给了我以下结果:
depth | node | parent
-------+------+--------
1 | 1 |
1 | 2 |
1 | 3 |
1 | 4 |
2 | 5 | 1
2 | 6 | 1
2 | 7 | 1
2 | 8 | 1
2 | 10 | 1
2 | 15 | 3
2 | 16 | 3
2 | 17 | 3
3 | 9 | 6
3 | 11 | 6
3 | 13 | 6
3 | 14 | 6
3 | 18 | 15
4 | 12 | 9
Run Code Online (Sandbox Code Playgroud)
您可能已经注意到,没有ORDER BY子句,因此没有定义顺序。您在此处看到的顺序是从根节点到更深的节点。
我将如何对结果进行排序,因为它们会出现在展开的树视图中,正如您从下面的示例图片中看到的那样?

我基本上希望将子节点放在相应的父节点之后。如果两个或多个子节点具有相同的父节点,我希望它们按时间戳排序。基于上面的示例,这是我试图实现的所需输出顺序:
depth | node | parent | ts
-------+------+--------+---------
1 | 1 | | 2014-01-01 00:00:00
2 | 5 | 1 | 2014-01-01 00:10:00
2 | 6 | 1 | 2014-01-01 00:20:00
3 | 9 | 6 | 2014-01-01 00:25:00
4 | 12 | 9 | 2014-01-01 00:27:00
3 | 11 | 6 | 2014-01-01 00:26:00
3 | 13 | 6 | 2014-01-01 00:30:00
3 | 14 | 6 | 2014-01-01 00:36:00
2 | 7 | 1 | 2014-01-01 00:21:00
2 | 8 | 1 | 2014-01-01 00:22:00
2 | 10 | 1 | 2014-01-01 00:23:00
1 | 2 | | 2014-01-01 00:08:00
1 | 3 | | 2014-01-01 00:09:00
2 | 15 | 3 | 2014-01-01 10:00:00
3 | 18 | 15 | 2014-01-01 11:05:00
2 | 16 | 3 | 2014-01-01 11:00:00
2 | 17 | 3 | 2014-01-01 12:00:00
1 | 4 | | 2014-01-01 00:10:00
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 13
表示从根到叶的路径的数组应达到所需的排序顺序:
WITH RECURSIVE node_rec AS (
(SELECT 1 AS depth, ARRAY[node] AS path, *
FROM nodes
WHERE parent IS NULL
LIMIT 10
)
UNION ALL
SELECT r.depth + 1, r.path || n.node, n.*
FROM node_rec r
JOIN nodes n ON n.parent = r.node
WHERE r.depth < 4
)
SELECT *
FROM node_rec
ORDER BY path;
Run Code Online (Sandbox Code Playgroud)
如果两个或多个子节点具有相同的父节点,我希望它们按时间戳排序。
将路径向根移动一个并按该列另外排序:
WITH RECURSIVE node_rec AS (
(SELECT 1 AS depth, ARRAY[node] AS path, *
FROM nodes
WHERE parent IS NULL
LIMIT 10
)
UNION ALL
SELECT r.depth + 1, r.path || n.parent, n.*
FROM node_rec r
JOIN nodes n ON n.parent = r.node
WHERE r.depth < 4
)
SELECT *
FROM node_rec
ORDER BY path, ts;Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10457 次 |
| 最近记录: |