PostgreSQL:循环直到条件为真

时间:2012-08-07 06:31:32

标签: postgresql loops while-loop postgresql-9.1

我正在尝试编写一个查询,该查询通过从指定值开始的数据库“循环”,直到条件为真。例如,假设我在TABLE示例中有以下条目:

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,LOOP结束并返回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中执行等效操作。

如果您有任何疑问或需要其他信息,请与我们联系。谢谢!

1 个答案:

答案 0 :(得分:10)

您对SQL的想法是错误的。不要考虑循环,条件和变量;相反,考虑如何描述您想要的数据。棘手的部分是你希望查询引用它自己的结果,这就是recursive CTEs的用途:

  

可选的RECURSIVE修饰符将WITH从仅仅语法上的便利转变为一种功能,该功能可以完成标准SQL中无法实现的功能。使用RECURSIVEWITH查询可以引用自己的输出。

你正在寻找这样的东西:

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 |       

然后你可以把它放回到一个路径中,这个路径在数据库之外会更加link-listy(或者你的客户语言中适合的任何东西)。当然,您不必包含parent,但包括它将帮助您修复“指针”。