递归 CTE 如何与文档中的示例一起使用?
How does recursive CTE work with example in the doc?
我今天正在研究 CTE 文档并尝试使用下面的示例(根据文档中的示例稍作修改):
WITH RECURSIVE t(n) AS (
VALUES (1), (2)
UNION ALL
(
SELECT n + 1
FROM t
WHERE n < 100
)
)
SELECT * FROM t;
这段代码输出
n
-----
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
...
这本身就很好。但是,在文档中,解释如下 (https://www.postgresql.org/docs/9.1/static/queries-with.html):
- Evaluate the non-recursive term. For
UNION
(but not UNION ALL
),
discard duplicate rows. Include all remaining rows in the result of
the recursive query, and also place them in a temporary working
table.
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
(but
not UNION ALL
), discard duplicate rows and rows that duplicate any
previous result row. 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.
我对解释的解读如下:
最初,我们将 (1), (2)
插入工作 table。然后在递归步骤中,我们采用工作 table,目前有 (1), (2)
,UNION ALL
递归步骤的结果,returns (2), (3)
,以及然后将结果放入中级table.
所以在第一次递归调用之后,我们有 (1), (2)
在 工作 table 和 (1), (2), (2), (3)
在 中间 table.
然后我们把workingtable的值替换成intermediatetable的值,然后清空 中间 table。所以现在工作table有(1), (2), (2), (3)
和中级table是空的
现在下一个递归调用,我们将采用包含 (1), (2), (2), (3)
的 工作 table,对其进行递归,产生 (2), (3), (3), (4)
,并将其附加到工作 table。所以工作table现在应该有(1), (2), (2), (3), (2), (3), (3), (4)
。然而,结果开始于
(1), (2), (2), (3), (3), (3), (4), (4)
等等
谁能告诉我我的推理哪里出了问题?
1,2 = 1,2 -> keep
1,2 plus 1 = 2,3 -> keep
2,3 plus 1 = 3,4 -> keep
3,4 plus 1 = 4,5 -> keep
结果是 1,2,2,3,3,4,4,5, ....
工作 table 只有前一个结果
你似乎混淆了结果和中间table,不一样。
(1), (2)
由“非递归”项产生并放置在 结果中 .
(1), (2)
也进入 工作 table.
-- 从这里开始迭代
(2), (3)
由“递归”项生成并添加到 结果 .
(2), (3)
也放在中间table.
(2), (3)
中级table的内容移至工作table.
-- 迭代
正如手册在此处添加的那样 (link to the current manual):
Strictly speaking, this process is iteration not recursion, but RECURSIVE
is the terminology chosen by the SQL standards committee.
与您的具体误解无关,只是为了解释我对“递归”的引用。
我今天正在研究 CTE 文档并尝试使用下面的示例(根据文档中的示例稍作修改):
WITH RECURSIVE t(n) AS (
VALUES (1), (2)
UNION ALL
(
SELECT n + 1
FROM t
WHERE n < 100
)
)
SELECT * FROM t;
这段代码输出
n
-----
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
...
这本身就很好。但是,在文档中,解释如下 (https://www.postgresql.org/docs/9.1/static/queries-with.html):
- Evaluate the non-recursive term. For
UNION
(but notUNION ALL
), discard duplicate rows. Include all remaining rows in the result of the recursive query, and also place them in a temporary working table.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
(but notUNION ALL
), discard duplicate rows and rows that duplicate any previous result row. 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.
我对解释的解读如下:
最初,我们将 (1), (2)
插入工作 table。然后在递归步骤中,我们采用工作 table,目前有 (1), (2)
,UNION ALL
递归步骤的结果,returns (2), (3)
,以及然后将结果放入中级table.
所以在第一次递归调用之后,我们有 (1), (2)
在 工作 table 和 (1), (2), (2), (3)
在 中间 table.
然后我们把workingtable的值替换成intermediatetable的值,然后清空 中间 table。所以现在工作table有(1), (2), (2), (3)
和中级table是空的
现在下一个递归调用,我们将采用包含 (1), (2), (2), (3)
的 工作 table,对其进行递归,产生 (2), (3), (3), (4)
,并将其附加到工作 table。所以工作table现在应该有(1), (2), (2), (3), (2), (3), (3), (4)
。然而,结果开始于
(1), (2), (2), (3), (3), (3), (4), (4)
等等
谁能告诉我我的推理哪里出了问题?
1,2 = 1,2 -> keep
1,2 plus 1 = 2,3 -> keep
2,3 plus 1 = 3,4 -> keep
3,4 plus 1 = 4,5 -> keep
结果是 1,2,2,3,3,4,4,5, ....
工作 table 只有前一个结果
你似乎混淆了结果和中间table,不一样。
(1), (2)
由“非递归”项产生并放置在 结果中 .
(1), (2)
也进入 工作 table.
-- 从这里开始迭代
(2), (3)
由“递归”项生成并添加到 结果 .
(2), (3)
也放在中间table.
(2), (3)
中级table的内容移至工作table.
-- 迭代
正如手册在此处添加的那样 (link to the current manual):
Strictly speaking, this process is iteration not recursion, but
RECURSIVE
is the terminology chosen by the SQL standards committee.
与您的具体误解无关,只是为了解释我对“递归”的引用。