我一直在阅读Postgres中的Query。
这令我感到惊讶WITH RECURSIVE t(n) AS (
VALUES (1)
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;
我无法理解查询的评估是如何运作的。
有关SQL中递归语句如何发生故障的任何见解。
答案 0 :(得分:4)
这称为公用表表达式,是一种在SQL中表达递归查询的方法:
t(n)
将CTE的名称定义为t
,其中一列名为n
。它类似于派生表的别名:
select ...
from (
...
) as t(n);
递归以值1开始(即values (1)
部分),然后递归加1,直到达到99。因此它生成从1到99的数字。然后最终查询然后总结所有这些数字。
n
是一个列名,不是一个&#34;变量&#34;和#34;任务&#34;以与任何数据检索相同的方式发生。
WITH RECURSIVE t(n) AS (
VALUES (1) --<< this is the recursion "root"
UNION ALL
SELECT n+1 FROM t WHERE n < 100 --<< this is the "recursive part"
)
SELECT sum(n) FROM t;
如果你&#34;展开&#34;递归(实际上是一个迭代)然后你最终得到这样的东西:
select x.n + 1
from (
select x.n + 1
from (
select x.n + 1
from (
select x.n + 1
from (
values (1)
) as x(n)
) as x(n)
) as x(n)
) as x(n)
手册中的更多细节:
https://www.postgresql.org/docs/current/static/queries-with.html
答案 1 :(得分:0)
如果您正在寻找它的评估方式,则递归分两个阶段进行。
现在,通常在数据库中,当我们进行命令式编程时,我们会以与我们想到的不同的方式来思考“功能”。在数据库术语中,思考函数的最佳方式是“对应每个域值的对应关系,您只有一个对应的值”。因此,当前的挑战之一就是停止在编程功能方面进行思考。甚至用户定义的函数最好以另一种方式考虑,因为它避免了关于运行查询和查询规划器的交叉点的很多潜在的麻烦...所以它可能看起来像一个函数,但这是不正确的。
相反,WITH子句使用不同的,几乎相反的符号。在这里,你有一个名称t
,在元组结构(n)
后面(在这种情况下可选)。所以这不是带参数的函数,而是与结构的关系。
所以这会如何分解:
SELECT 1 as n where n < 100
UNION ALL
SELECT n + 1 FROM (SELECT 1 as n) where n < 100
UNION ALL
SELECT n + 1 FROM (SELECT n + 1 FROM (SELECT 1 as n)) where n < 100
当然这是一种简化,因为在内部我们会跟踪cte状态并继续加入最后一次迭代,所以在实践中这些会折回到接近线性的复杂度(而上面的图表表明性能要差得多)
所以实际上你会得到更像的东西:
SELECT 1 as n where 1 < 100
UNION ALL
SELECT 1 + 1 as n where 1 + 1 < 100
UNION ALL
SELECT 2 + 1 AS n WHERE 2 + 1 < 100
...
本质上,以前的值继续存在。