📜  PostgreSQL – 使用 CTE 的递归查询

📅  最后修改于: 2022-05-13 01:57:15.535000             🧑  作者: Mango

PostgreSQL – 使用 CTE 的递归查询

严格来说,这个过程是迭代,不是递归,而是 RECURSIVE 是 SQL 标准委员会选择的术语。

Postgres 递归查询的一般结构包含,

  1. 非递归选择语句
  2. 联合或联合所有
  3. 递归选择语句
WITH RECURSIVE name_cte AS (
SELECT statement  /* non-recursive statement */
UNION [ALL]
SELECT statement  /*recursive statement referencing the above select statement */
)
SELECT * FROM name_cte;

Postres 递归查询是如何工作的:

  1. 评估非递归语句并创建临时表
  2. 评估递归项并将它们添加到临时表
  3. 重复步骤 2,直到工作台为空。

unionunion all的区别在于union all允许重复, union 不允许任何重复。

例子:



WITH RECURSIVE tens AS (
   SELECT 1 as n
 UNION ALL
   SELECT n+1 FROM tens
)
SELECT n FROM tens limit 10;

这是打印前 10 个自然数的 Postres 递归查询的基本示例。

Postres递归查询以查找自然数的阶乘:

WITH RECURSIVE fact (n, factorial)
AS (
    SELECT 1 as n, 5 as factorial
union all
    SELECT n+1, factorial*n FROM fact where n < 5
)
SELECT * FROM fact;

此查询输出两个表,一个包含前五个自然数,另一个包含为查找阶乘而执行的计算。

我们只能打印最后一行,但在这里我们可以看到迭代和计算是如何发生的。

Postres递归查询打印斐波那契数列:

WITH RECURSIVE fibb
AS (
    SELECT 1::bigint as n, 0::bigint as a, 1::bigint as b
UNION ALL
    SELECT n+1, b as a, (a+b) as b FROM fibb
)
SELECT b FROM fibb limit 10;

这将打印最多 10 的斐波那契数列。



借助 Postgres 递归查询,我们可以找到组织层次结构:。

要创建表:

INSERT INTO employees (
employee_id,
full_name,
manager_id
)
VALUES
(1, 'Abhi', NULL),
(2, 'Bhargav', 1),
(3, 'Chay', 1),
(4, 'Dravid', 1),
(5, 'Erin', 1),
(6, 'Ford', 2),
(7, 'Gagan', 2),
(8, 'Harry', 3),
(9, 'Isaac', 3),
(10, 'Jack', 4),
(11, 'Kiran', 5);

Abhi 是老板,他会在第一层。 Bhargav、Chay、Dravid、Erin 处于下一个级别,其余的将是最后一个级别。

询问:

WITH RECURSIVE subordinates AS (
SELECT employee_id, manager_id, full_name, 0 as level
FROM employees
WHERE manager_id IS NULL
UNION ALL
SELECT e.employee_id, e.manager_id, e.full_name, level+1
FROM employees e
INNER JOIN subordinates s ON s.employee_id = e.manager_id
)  
SELECT * FROM subordinates;

输出将是: