6

我正在尝试编写一个查询,该查询从指定值开始“循环”数据库,直到条件为真。例如,假设我在 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;

首先,这会产生一个错误(“'while' 处或附近的语法错误”)。其次,我不知道如何在每次迭代后更新“id”。

在像 Python 这样的编程语言中,我可能会使用一个初始化为 4 的变量,然后在每次迭代时对其进行更新……不知道如何在 Postgres 中进行等效操作。

如果您有任何问题或需要更多信息,请告诉我。谢谢!

4

1 回答 1

11

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

optionalRECURSIVE修饰符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 |       

然后您可以将它们重新组合到数据库之外的更链表(或任何适合您的客户端语言)的路径中。当然,您不必包括parent在内,但包括在内将帮助您修复“指针”。

于 2012-08-07T07:07:55.710 回答