按赞成票对 LTree 排序
Sort LTree by Upvotes
我正在写一个评论系统。我已经能够按照这里的教程获得层次结构 (http://www.postgresonline.com/journal/archives/173-Using-LTree-to-Represent-and-Query-Hierarchy-and-Tree-Structures.html)
SELECT n.node_path AS PATH,
n.note_id AS _1,
n.note_no AS _2,
n.public_key AS _3,
n.upvotes AS _4
FROM public.comment_table AS n
INNER JOIN public.comment_table AS a ON (a.node_path @> n.node_path)
GROUP BY _1, PATH
ORDER BY PATH
但是,我无法通过投票对行进行排序。我不能在这里简单地 ORDER BY PATH, n.upvotes
因为在同一个线程上的回复会有不同的 node paths
。 node_paths
是使用 public_key
.
计算的
从例子中给出
a (0 upvotes)
-> b (0 upvotes)
-> c (1 upvote)
d (1 upvote)
-> e (0 upvotes)
b
和 c
的节点路径将分别为 a.b
和 a.c
。我不能简单地从节点路径和 ORDER BY
中减去 b
和 c
。如果我这样做,结果会是这个顺序:
a
d
-> b
-> c
-> e
这是有道理的,因为如果您从 node_path
中删除每一行的 public_key
,它只会按最短的 node_path
到最长的排序。
我如何编写查询以生成正确的层次结构并按赞成票排序,如下所示:
d (1)
-> e (0)
a (0)
-> c (1)
-> b (0)
假设赞成票数不断变化,并且您选择了 ltree
路线来避免递归,我想不出一个不需要递归的解决方案,因为每一行都需要访问对其祖先的计数进行投票,以找到将自己置于结果中的位置。
with recursive base as (
select node_path, upvotes,
array[row_number() over (order by upvotes desc, node_path)] as sort_path
from comment_table
where nlevel(node_path) = 1
union all
select c.node_path, c.upvotes,
p.sort_path||row_number() over (order by c.upvotes desc, c.node_path)
from base p
join comment_table c
on subpath(c.node_path, 0, -1) = p.node_path
)
select * from base order by sort_path;
node_path | upvotes | sort_path
-----------+---------+-----------
d | 1 | {1}
d.e | 0 | {1,3}
a | 0 | {2}
a.c | 1 | {2,1}
a.b | 0 | {2,2}
(5 rows)
我正在写一个评论系统。我已经能够按照这里的教程获得层次结构 (http://www.postgresonline.com/journal/archives/173-Using-LTree-to-Represent-and-Query-Hierarchy-and-Tree-Structures.html)
SELECT n.node_path AS PATH,
n.note_id AS _1,
n.note_no AS _2,
n.public_key AS _3,
n.upvotes AS _4
FROM public.comment_table AS n
INNER JOIN public.comment_table AS a ON (a.node_path @> n.node_path)
GROUP BY _1, PATH
ORDER BY PATH
但是,我无法通过投票对行进行排序。我不能在这里简单地 ORDER BY PATH, n.upvotes
因为在同一个线程上的回复会有不同的 node paths
。 node_paths
是使用 public_key
.
从例子中给出
a (0 upvotes)
-> b (0 upvotes)
-> c (1 upvote)
d (1 upvote)
-> e (0 upvotes)
b
和 c
的节点路径将分别为 a.b
和 a.c
。我不能简单地从节点路径和 ORDER BY
中减去 b
和 c
。如果我这样做,结果会是这个顺序:
a
d
-> b
-> c
-> e
这是有道理的,因为如果您从 node_path
中删除每一行的 public_key
,它只会按最短的 node_path
到最长的排序。
我如何编写查询以生成正确的层次结构并按赞成票排序,如下所示:
d (1)
-> e (0)
a (0)
-> c (1)
-> b (0)
假设赞成票数不断变化,并且您选择了 ltree
路线来避免递归,我想不出一个不需要递归的解决方案,因为每一行都需要访问对其祖先的计数进行投票,以找到将自己置于结果中的位置。
with recursive base as (
select node_path, upvotes,
array[row_number() over (order by upvotes desc, node_path)] as sort_path
from comment_table
where nlevel(node_path) = 1
union all
select c.node_path, c.upvotes,
p.sort_path||row_number() over (order by c.upvotes desc, c.node_path)
from base p
join comment_table c
on subpath(c.node_path, 0, -1) = p.node_path
)
select * from base order by sort_path;
node_path | upvotes | sort_path
-----------+---------+-----------
d | 1 | {1}
d.e | 0 | {1,3}
a | 0 | {2}
a.c | 1 | {2,1}
a.b | 0 | {2,2}
(5 rows)