1

我正在写一个评论系统。我已经能够按照这里的教程获得层次结构(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)

ban的节点路径分别ca.ba.c。我不能简单地从节点路径和它们中减去b和。如果我这样做,它将导致以下顺序:cORDER BY

a
d
-> b
-> c
-> e

这是有道理的,因为如果您public_key从中删除每一行node_path,它将简单地按最短node_path到最长排序。

如何编写一个查询,该查询将产生正确的层次结构并按如下方式排序:

d (1)
-> e (0)
a (0)
-> c (1)
-> b (0)
4

1 回答 1

2

假设赞成票数不断变化,并且您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)
于 2020-07-24T14:51:06.310 回答