我有一个复杂的PSQL函数返回表记录的SETOF
(树中叶子记录的祖先路径,yikes),通常一次只有几个记录 - 祖先 - 这适合于完美的应用程序的其余部分。
例如,给定记录:
id: 5, parent_id: null
id: 1, parent_id: 5
id: 3, parent_id: 1
该函数应该被调用为get_ancestry(3)
我希望它按照这个确切的顺序返回包含SETOF
的{{1}}条记录 - 而且顺序很明显很重要。
然而,有一个一个小小的重要位置我需要以完全相反的顺序迭代3, 1, 5
的记录,在之前的例子中,预期的结果将是是SETOF
。
或者换句话说给定一个返回SETOF的函数,如何编写一个以相反的顺序返回相同SETOF的函数?
5, 1, 3
我可以帮助自己 - 我可以轻松地计算它,但是如何将它添加到属于表的记录对象?ORDER BY
转换成数组然后反转数组,但没有发现任何谷歌搜索 - 不是关于反转数组,也不是将SETOF
转换为数组SETOF
属性,如果记录是顶级的,则等于0,记录'孩子会有level
等,但是为超级忙添加另一列必须以某种方式更好地工作的这一个查询的不断更新的表似乎是错误的怎么办?
答案 0 :(得分:1)
我想添加一个关卡属性
您不必将其添加到表中,您可以在查询中动态计算。
这样的事情:
with recursive tree (id, parent_id, level) as (
select id, parent_id, 1 as level
from the_table
where parent_id is null
union all
select c.id, c.parent_id, p.level + 1
from the_table c
join data p on p.id = c.parent_id
)
select *
from tree;
如果要将树从树叶移动到父级,则需要更改递归查询:
with recursive tree (id, parent_id, level) as (
select id, parent_id, 1 as level
from the_table
where id = 42
union all
select x.id, x.parent_id, p.level + 1
from the_table x
join data p on x.id = p.parent_id
)
select *
from tree;
请注意,在这种情况下,级别列的“含义”是相反的。它基本上定义了每一行与起点的距离。它不是整个层次结构中的整体级别。
以上内容可以放入函数中:
create function get_tree(p_start_with integer)
returns table(id integer, parent_id integer, level integer)
as
$$
... the query from above using the p_start_with parameter
$$
language sql;
然后你可以使用
select *
from get_tree(42)
order by level desc;
如果对您来说很重要,您还应该添加另一列来定义同一级别的子级顺序。或者只使用order by level desc, id desc
之类的内容来获得同一级别所有元素的一致顺序。
答案 1 :(得分:0)
要反转返回的订单,您可以执行子查询并按原始行号排序。重要的是要强调row_number()over()正在使用行"因为它们来了"所以你的get_ancestry()函数必须控制这个顺序,否则你会冒不一致的结果。
select * from
(select a.*,
row_number() over() as sortID
from get_ancestry(3) a) b
order by sortID desc;