2017-06-01 20 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