在保持结构的同时对树进行排序

时间:2011-06-25 00:40:14

标签: sql postgresql sql-order-by materialized-path-pattern

我有一棵使用物化路径的树。

该表类似于:

+-------------+--------+----------+-------+
| path        | depth  | children | score |
+-------------+--------+----------+-------+
| 0001        | 1      | 3        | 5     |
| 00010001    | 2      | 0        | -3    |
| 00010002    | 2      | 0        | 27    |
| 00010003    | 2      | 0        | 10    |
| 0002        | 1      | 2        | 12    |
| 00020001    | 2      | 0        | 0     |
| 00020002    | 2      | 1        | 3     |
| 00020002001 | 3      | 0        | 1     |
+-------------+--------+----------+-------+

我希望在保持树结构的同时按score列进行排序 重要的是孩子在他们的父母之下。

+-------------+--------+----------+-------+
| path        | depth  | children | score |
+-------------+--------+----------+-------+
| 0002        | 1      | 2        | 12    |
| 00020002    | 2      | 1        | 3     |
| 00020002001 | 3      | 0        | 1     |
| 00020001    | 2      | 0        | 0     |
| 0001        | 1      | 3        | 5     |
| 00010002    | 2      | 0        | 27    |
| 00010003    | 2      | 0        | 10    |
| 00010001    | 2      | 0        | -3    |
+-------------+--------+----------+-------+

path列仅用于数据库,因此不必是顺序的。

我目前使用的SQL对树进行排序,以便我可以构建它:

SELECT path, depth, children, score FROM mytable ORDER BY path ASC

1 个答案:

答案 0 :(得分:1)

您将需要递归查询和窗口函数。它看起来与此类似:

with recursive
ordered_tree as (
select tree.*,
       array[row_number() over w] as score_path
from   tree
where  depth = 1
window w as (order by tree.score desc)
union all
select tree.*,
       parent.score_path || array[row_number() over w] as score_path
from   tree
join   ordered_tree as parent on parent.id = tree.parent_id
window w as (partition by tree.parent_id order by tree.score desc)
)
select *
from   ordered_tree
order by score_path

注意:如果您的设置很大,上面的内容会相当慢......