2017-06-01 74 views
1

我有一个复杂的PSQL函数,它返回表记录(树中叶记录的祖先路径,yikes)的SETOF,通常每次只有几个记录 - 祖先 - 这适合于应用程序的其余部分完美。如何在Postgres中反转SETOF的顺序?

例如,假设记录:

id: 5, parent_id: null 
id: 1, parent_id: 5 
id: 3, parent_id: 1 

应的功能被称为get_ancestry(3)我希望它返回SETOF记录严格按照此顺序包含3, 1, 5 - 和顺序很重要明显。

然而,这一个小小的重要的地方,我需要之前迭代的确切相反的顺序SETOF的记录,在本例中,预期的结果将是5, 1, 3

或者换句话说给出了一个返回SETOF的函数,如何编写一个函数以相反的顺序返回相同的SETOF?

  • 没有ORDER BY我可以用它来帮助自己一起 - 我可以很容易地计算它几乎,但如何将它添加到属于一个表中的记录对象?
  • 我想转换SETOF到一个数组,然后反向阵列的,但没有发现任何使用Google - 不是反转阵列,也不约转换SETOF到一个数组
  • 我想加入一个level属性的这将是等于0如果记录是顶级的,那记录的孩子将有level=1等等,但是将另一列添加到对于这个查询的超忙不断更新表中,其中必须以某种方式更好地工作似乎只是错误
  • 重写复杂函数以完全相同的方式完成相当棘手的逻辑,但递归其他路径看起来像是维护/ bugfi x噩梦

怎么办?

+2

请** [编辑] **您的问题,并添加一些样本数据和基于该数据的预期输出。 [**格式化文本**](http://stackoverflow.com/help/formatting)请,[**没有屏幕截图**](http://meta.stackoverflow.com/questions/285551/why-may -i-不上传图像-的代码上那么当灰化-A-问题/ 285557#285557)。 ** [**]您的问题 - 请勿**在论坛中发布代码或其他信息。 –

+0

@a_horse_with_no_name按要求完成! – bbozo

+0

说实话,整个问题都在标题中,看起来很清楚。 “给定一个返回SETOF的函数,如何编写一个以相反顺序返回相同SETOF的函数”。 – bbozo

回答

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的东西来获得同一级别上所有元素的一致顺序。

+0

嗯,递归'with'查询,谢谢,我会玩它:) – bbozo

+0

啊,是的,问题是,函数需要开始不从任何顶部('parent_id为null'),但从一个特定的叶然后遍历到顶部(因为每个父母有很多孩子)。但是,你给我一个好主意<3 – bbozo

+1

@bbozo:这不是问题。您需要更改非递归部分中的条件以及递归部分中的连接。 –

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; 
+0

Interrresting,yes'get_ancestry'返回“行数”,这应该工作 – bbozo