繁体   English   中英

关于WITH RECURSIVE查询Postgres的可能解释

[英]Possible explanation on WITH RECURSIVE Query Postgres

我一直在阅读Postgres中的With Query。 这就是我很惊讶的地方

WITH RECURSIVE t(n) AS (
    VALUES (1)
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;

我不明白查询的评估如何工作。

  • t(n)听起来像是带有参数的函数。 n的值如何传递。

关于SQL递归语句如何分解的任何见解。

这称为公用表表达式,是在SQL中表示递归查询的一种方式:

t(n)将CTE的名称定义为t ,其中有一列称为n 它类似于派生表的别名:

select ... 
from (
  ...
) ;

递归以值1(即values (1)一部分)开始,然后递归地将values (1) ,直到达到99。 因此它将生成从1到99的数字。然后最终查询将所有这些数字相加。

n是列名, 而不是 “变量”,并且“赋值”的发生方式与任何数据检索相同。

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;

如果您“展开”递归(实际上是一个迭代),那么您将得到如下结果:

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. 根执行一次。
  2. 递归部分一直执行到没有行返回为止。 关于这一点,文档有点模糊。

现在,通常在数据库中,我们对“功能”的思考方式与我们进行命令式编程时所想到的方式不同。 用数据库术语来说,想到一个函数的最佳方法是“一种对应关系,对于每个域值,您都具有一个对应的值。” 因此,当前的挑战之一是停止就编程功能进行思考。 甚至用户定义的函数也最好用这种其他方式来考虑,因为它避免了在运行查询和查询计划程序的交集方面的许多潜在麻烦。因此,它看起来像一个函数,但这是不正确的。

相反,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
 ...

本质上,以前的值会保留下来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM