PostgreSQL with子句 递归

本文详细介绍了在PostgreSQL中使用with子句进行辅助报表和复杂查询的方法,包括创建表、插入测试数据、使用with子句进行查询、结合使用多个with子句以及递归查询的应用。通过实例展示了如何简化大型查询过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在PostgreSQL里,with子句提供了一种方法写一个大的查询中使用的辅助报表与查询。它有助于打破复杂和大型查询简单易读的形式。

1. 建表
postgres=# create table tb9(id serial primary key,name character varying, parentid integer);
CREATE TABLE
postgres=# \d tb9
                               Table "public.tb9"
  Column  |       Type        |                    Modifiers                     
----------+-------------------+--------------------------------------------------
 id       | integer           | not null default nextval('tb9_id_seq'::regclass)
 name     | character varying | 
 parentid | integer           | 
Indexes:
    "tb9_pkey" PRIMARY KEY, btree (id)
2. 插入测试数据
postgres=# insert into tb9 values(generate_series(1,5),'john',0);
INSERT 0 5
postgres=# insert into tb9 values(6,'john1',1);
INSERT 0 1
postgres=# insert into tb9 values(7,'john2',1);
INSERT 0 1
postgres=# insert into tb9 values(8,'john11',6);
INSERT 0 1
postgres=# select * from tb9;
 id |  name  | parentid 
----+--------+----------
  1 | john   |        0
  2 | john   |        0
  3 | john   |        0
  4 | john   |        0
  5 | john   |        0
  6 | john1  |        1
  7 | john2  |        1
  8 | john11 |        6
(8 rows)
3. with子句
postgres=# with t as (select * from tb9 where parentid=1) select count(0) from t;
 count 
-------
     2
(1 row)
postgres=# with t(a,b,c) as (select * from tb9 where parentid=1) select a,b,c from t;
 a |   b   | c 
---+-------+---
 6 | john1 | 1
 7 | john2 | 1
(2 rows)
4. 多个with子句的结合使用
parentid=1的记录的所有子记录
postgres=# with t1 as (select * from tb9),t2 as(select * from tb9 where parentid=1) select t1.* from t1,t2 where t2.id=t1.parentid;
 id |  name  | parentid 
----+--------+----------
  8 | john11 |        6
(1 row)
5. 递归
id为1的记录的所有子记录
postgres=# with recursive t as(select id,name,parentid from tb9 where id=1 union all select k.id,k.name,k.parentid from tb9 k,t where t.id=k.parentid) select * from t;
 id |  name  | parentid 
----+--------+----------
  1 | john   |        0
  6 | john1  |        1
  7 | john2  |        1
  8 | john11 |        6
  9 | john21 |        7
(5 rows)


PostgreSQL 中处理涉及三个表的递归查询通常会使用 `WITH RECURSIVE` 子句。这种查询允许你在一张或多张表之间构建复杂的关系,并逐步迭代计算结果集。 ### 示例场景 假设我们有三张表: 1. **员工 (employees)** - 包含所有员工的基本信息。 ```sql CREATE TABLE employees ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, manager_id INT REFERENCES employees(id) ); ``` 2. **部门 (departments)** - 描述每个部门的信息及其主管(也是某个员工)。 ```sql CREATE TABLE departments ( dept_id SERIAL PRIMARY KEY, department_name TEXT NOT NULL, head_id INT REFERENCES employees(id) ON DELETE SET NULL ); ``` 3. **项目 (projects)** - 记录各个项目的负责人以及所在部门。 ```sql CREATE TABLE projects ( proj_id SERIAL PRIMARY KEY, project_name TEXT NOT NULL, leader_id INT REFERENCES employees(id), dept_id INT REFERENCES departments(dept_id) ); ``` #### 目标: 我们需要找出所有的“经理链”,即从最顶层领导开始到每一个直接下属、再依次往下直到最低级别的普通员工。这涉及到跨越上述表格之间的层级关系,特别是通过 `manager_id` 字段建立起来的层次结构。 ### SQL 查询示例 ```sql WITH RECURSIVE hierarchy AS ( -- 基础成员选择:找到初始节点(例如没有上级的总经理) SELECT e.id, e.name, ARRAY[e.name] as path, 0 as level FROM employees e WHERE e.manager_id IS NULL UNION ALL -- 迭代部分:添加下一层级的所有记录 SELECT e.id, e.name, h.path || e.name, h.level + 1 FROM employees e JOIN hierarchy h ON e.manager_id = h.id ) SELECT * FROM hierarchy; ``` 此查询首先选取了没有任何上司 (`manager_id`) 的顶级管理者作为起点;然后,在每次循环中加入该管理者的直属下级们,如此往复直至遍历完整个组织架构图。最终得到的结果集中包含了每一层管理人员的名字序列及他们各自所在的级别深度。 如果你希望进一步关联其他两张表获取更详细的数据,则可以在最后的选择语句里加上适当的JOIN操作。比如结合`departments` 表查看各部门负责人的管理层级等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值