2012-08-07 81 views
4

我想寫一個查詢「循環」通過數據庫開始在指定的值,直到條件爲真。例如,假設我在表例如以下輸入:PostgreSQL:循環直到條件爲真

id, parent, cond 
1,  , True 
2, 1  , False 
3, 1  , False 
4, 2  , False 
... ... ... 

我想要查詢其作爲輸入(例如)4,並且將返回的2和1的方法之處在於查詢中的值匹配id,如果cond == False,則會查看父級(id = 2)。由於cond = False在第二行,「父」id將被選中(1)。在第一排看現在,因爲COND = TRUE,則循環結束,返回1和2

我知道查詢

SELECT parent FROM example WHERE id = 4; 

會產生父ID 2

所以我在創建一個循環徒勞:

WHILE (SELECT cond FROM example) = False 
LOOP SELECT parent FROM example WHERE id = 4 
END LOOP; 

首先,這產生一個錯誤(「在語法錯誤或接近‘而’」)。其次,我不知道如何在每次迭代後更新「id」。

在像Python這樣的編程語言中,我可能會使用初始化爲4的變量,然後在每次迭代中更新它......不知道如何在Postgres中執行相同的操作。

如果您有任何問題或需要更多信息,請告知我們。謝謝!

回答

9

你對SQL的想法是錯誤的。不要用循環,條件和變量來思考;相反,想想如何描述你想要的數據。最棘手的部分是你要查詢引用它自己的結果,而這正是recursive CTEs是:

可選RECURSIVE修飾改變WITH從一個單純的語法便利成完成事情的標準沒有其他可能的功能SQL。使用RECURSIVE,一個WITH查詢可以引用它自己的輸出。

您正在尋找這樣的事情:

with recursive path as (
    select id, parent from T where id = 4 
    union all 
    select t.id, t.parent from T t join path p on t.id = p.parent 
) 
select id, parent 
from path 

這將會給你:

id | parent 
----+-------- 
    4 |  2 
    2 |  1 
    1 |  

,然後你可以把一起回來的,將是更加的路徑在數據庫外部鏈接列表(或其他任何適合您客戶端語言的內容)。當然你不必包括parent,但包括它會幫助你修正「指針」。

+0

謝謝。我不太清楚如何解決這個問題。非常感激。 – 2012-08-07 07:12:26