如何解释sql with-recursive语句? [英] How sql with-recursive statement interpreted?

查看:573
本文介绍了如何解释sql with-recursive语句?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一些关于理解递归如何工作的帮助。
更精确地为什么锚查询(非递归术语)不会复制到CTE的子调用中。我尝试最好单独理解,但我不确定。



首先让我们以PostgreSQL为例,它是我找到的最简单的一个1至100):

 与回答t(n)AS(
值(1)
ALL
SELECT n + 1 FROM t WHERE n< 100)

SELECT sum(n)FROM t;

我的代码演练(我使用了以下链接):


$ b b


  1. 评估非递归项。 [...]



    包含递归查询结果中的所有剩余行,并将它们放在临时工作表中。


  2. 只要工作表不为空,请重复以下步骤:




    • 评估递归项,将工作表的当前内容替换为递归自引用。对于UNION [...]。
      包含递归查询结果中的所有剩余行,并将它们放在临时中间表中。


    • 替换工作的内容



LVL 0:


  1. 非递归部分




    • CTE:(N)1

    • 工作表:(N)1


  2. 递归零件




    • CTE:(N)1

    • 工作表:( N)1

    • 中等表格(N)2


(这是我认为的部分) - WORKING TABLE的替换



所以递归t将使用WORKING TABLE来做SELECT n + 1,并将结果放在INTERMEDIATE TABLE中。


  1. UNION ALL




    • CTE:(N)1 2

    • 工作表:(N)2

    • 中级表:清除


  2. 然后我们通过电话t进入下一个lvl?
    (因为END条件WHERE n <100 = FALSE)


LVL 1:



我们知道coz postgreSQL说它只要工作表不为空,重复递归步骤
所以它将重复步骤2.和3.(if我是正确的)直到END条件,然后做SUM。



但是如果我只是遍历t的下一个lvl的调用,我们不应该做VALUES(1) ?



我真的很困惑如何可能。



最好的问候,
Falt4rm




解决方案

这里没有递归,我认为这是你困惑的地方。



从PostgreSQL文档: http://www.postgresql.org/docs/9.4/static/queries-with。 html

 注意:严格来说,这个过程是迭代不递归,
,但RECURSIVE是术语由SQL标准委员会选择。

要改写这句话, WITH RECURSIVE 可以看作是一个简单的 WHILE 循环。

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

SELECT * FROM t;

这里有一些定制的伪代码来详细解释这个过程



#步骤1:初始化
LET cte_result = EMPTY
LET working_table = VALUES(1)
LET intermediate_table = EMPTY

#步骤2:结果初始化,合并初始化为cte_result
cte_result = cte_result UNION working_table

#步骤3:迭代测试
WHILE不是空的)DO
#步骤4:迭代选择,我们用working_table替换自引用
intermediate_table = SELECT n + 1 FROM working_table WHERE n< 100

#步骤5:迭代合并,将迭代结果合并到cte_result中
cte_result = cte_result UNION intermediate_table

#步骤6:迭代结束,准备下一次迭代
working_table = intermediate_table
intermediate_table = EMPTY
END WHILE

#步骤7:返回
返回cte_result

并使用示例

 #步骤1:初始化
cte_result:EMPTY | working_table:1 | intermediate_table:EMPTY

#步骤2:结果初始化
cte_result:1 | working_table:1 | middle_table:EMPTY

#步骤3:迭代测试
count(working_table)= 1#OK
#步骤4:迭代选择
cte_result:1 | working_table:1 | intermediate_table:2
#第5步:迭代合并
cte_result:1,2 | working_table:1 | intermediate_table:2
#步骤6:迭代结束
cte_result:1,2 | working_table:2 | middle_table:EMPTY

#步骤3:迭代测试
count(working_table)= 1#OK
#步骤4:迭代select
cte_result:1, working_table:2 | intermediate_table:3
#第5步:迭代合并
cte_result:1,2,3 | working_table:2 | intermediate_table:3
#步骤6:迭代结束
cte_result:1,2,3 | working_table:3 | middle_table:EMPTY

#... 97次迭代,你得到这个状态
cte_result:1,2,...,100 | working_table:100 | middle_table:EMPTY

#第3步:迭代测试
count(working_table)= 1#OK
#第4步:迭代选择,迭代查询不返回任何行WHERE子句
cte_result:1,2,...,100 | working_table:100 | middle_table:EMPTY
#第5步:迭代合并,没有什么合并到cte_result中
cte_result:1,2,...,100 | working_table:100 | intermediate_table:EMPTY
#步骤6:迭代结束
cte_result:1,2,...,100 | working_table:EMPTY | middle_table:EMPTY

#步骤3:迭代测试
count(working_table)= 0#STOP

#步骤7:return
cte_result: 2,...,100

所以CTE的结果是从1到100的所有数字。 p>

I would like to ask get some help about understanding how "with recursive" works. More precisely WHY the anchor query (the non-recursive term) isn't replicated into the sub call of the CTE. I tried my best to understand alone but I'm not sure.

First of all let's take the example of PostgreSQL which is the simplest one I found (make the sum of 1 to 100) :

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

    SELECT sum(n) FROM t;

My code walkthrough ( I used links below) :

  1. Evaluate the non-recursive term. For UNION [...].

    Include all remaining rows in the result of the recursive query, and also place them in a temporary working table.

  2. So long as the working table is not empty, repeat these steps:

    • Evaluate the recursive term, substituting the current contents of the working table for the recursive self-reference. For UNION [...]. Include all remaining rows in the result of the recursive query, and also place them in a temporary intermediate table.

    • Replace the contents of the working table with the contents of the intermediate table, then empty the intermediate table."

LVL 0 :

  1. non-recursive part

    • CTE : (N) 1
    • WORKING TABLE : (N) 1
  2. recursive part

    • CTE : (N) 1
    • WORKING TABLE : (N) 1
    • INTERMEDIATE TABLE (N) 2

(this is the part I mess around I think) - substitution of WORKING TABLE

So the recursive t will use WORKING TABLE to do SELECT n+1 and put the result in INTERMEDIATE TABLE.

  1. UNION ALL

    • CTE : (N) 1 2
    • WORKING TABLE : (N) 2
    • INTERMEDIATE TABLE : CLEANED
  2. Then we go into the next lvl by the call of t right? (because END condition WHERE n < 100 = FALSE)

LVL 1 :

We know coz postgreSQL says it "So long as the working table is not empty, repeat the recursive steps" So it will repeat the step 2. and 3. (if i'm correct) until END condition then do the SUM.

BUT if I just walkthrough the call of the next lvl of t should we not do VALUES(1) first ?

I'm really confused about how it is possible.

Best regards, Falt4rm

解决方案

There is no "recursion" taking place here and I think that this is where you get confused.

From the PostgreSQL documentation: http://www.postgresql.org/docs/9.4/static/queries-with.html

Note: Strictly speaking, this process is iteration not recursion, 
but RECURSIVE is the terminology chosen by the SQL standards committee.

To paraphrase this sentence, a WITH RECURSIVE can be viewed as a simple WHILE loop.

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

Here is some custom-made pseudo-code to explain this process in detail

# Step 1: initialisation
LET cte_result = EMPTY
LET working_table = VALUES (1)
LET intermediate_table = EMPTY

# Step 2: result initialisation, merge initialisation into cte_result
cte_result = cte_result UNION working_table

# Step 3: iteration test
WHILE (working_table is not empty) DO
    # Step 4: iteration select, we substitute the self-reference with working_table
    intermediate_table = SELECT n+1 FROM working_table WHERE n < 100

    # Step 5: iteration merge, merge the iteration result into cte_result
    cte_result = cte_result UNION intermediate_table

    # Step 6: iteration end, prepare for next iteration
    working_table = intermediate_table
    intermediate_table = EMPTY
END WHILE

# Step 7: return
RETURN cte_result

And using an example

# Step 1: initialisation
cte_result: EMPTY    | working_table: 1        | intermediate_table: EMPTY

# Step 2: result initialisation
cte_result: 1        | working_table: 1        | intermediate_table: EMPTY

# Step 3: iteration test
count(working_table) = 1 # OK
# Step 4: iteration select
cte_result: 1             | working_table: 1        | intermediate_table: 2
# Step 5: iteration merge
cte_result: 1, 2          | working_table: 1        | intermediate_table: 2
# Step 6: iteration end
cte_result: 1, 2          | working_table: 2        | intermediate_table: EMPTY

# Step 3: iteration test
count(working_table) = 1 # OK
# Step 4: iteration select
cte_result: 1, 2         | working_table: 2        | intermediate_table: 3
# Step 5: iteration merge
cte_result: 1, 2, 3      | working_table: 2        | intermediate_table: 3
# Step 6: iteration end
cte_result: 1, 2, 3      | working_table: 3        | intermediate_table: EMPTY

# … 97 more iterations and you get this state
cte_result: 1, 2, …, 100  | working_table: 100       | intermediate_table: EMPTY

# Step 3: iteration test
count(working_table) = 1 # OK
# Step 4: iteration select, the iteration query does not return any rows due to the WHERE clause
cte_result: 1, 2, …, 100  | working_table: 100       | intermediate_table: EMPTY
# Step 5: iteration merge, nothing is merged into the cte_result
cte_result: 1, 2, …, 100  | working_table: 100       | intermediate_table: EMPTY
# Step 6: iteration end
cte_result: 1, 2, …, 100  | working_table: EMPTY | intermediate_table: EMPTY

# Step 3: iteration test
count(working_table) = 0 # STOP

# Step 7: return
cte_result: 1, 2, …, 100

So the result of the CTE is all numbers from 1 to 100.

这篇关于如何解释sql with-recursive语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆