postgresql中的with查询

postgresql中的with查询_第1张图片

       WITH提供了一种编写辅助语句的方法,以便在较大的查询中使用。这些语句通常被称为公共表表达式或CTE,可以认为它们定义了仅为一个查询而存在的临时表。WITH子句中的每个辅助语句可以是SELECT、INSERT、UPDATE或DELETE;WITH子句本身附加到主语句,主语句也可以是SELECT、INSERT、UPDATE或DELETE。

先通过一个简单的CTE示例了解WITH查询,如下所示:

WITH t as
  (SELECT generate_series(1,3))
SELECT * FROM t;

结果:

postgresql中的with查询_第2张图片

       这个简单的CTE示例中,一开始定义了一条辅助语句t取数,之后在主查询语句中查询t,定义的辅助语句就像是定义了一张临时表,对于复杂查询如果不使用CTE,可以通过创建视图方式简化SQL。

       可选的 RECURSIVE修饰符从单纯的语法便利变成了一个功能,可以完成标准SQL中不可能完成的任务。使用RECURSIVE,WITH查询可以引用它自己的输出。从而实现递归,一般用于层次结构或树状结构的应用场景。注:严格地说,这个过程是迭代而不是递归,但是递归是SQL标准委员会选择的术语。

例如,创建表准备数据:

create table area(id int,name text,fatherid int);

insert into area values(1, '中国', 0),(2, '北京', 1),(3, '上海', 1),(4, '昌平区', 2),(5, '黄浦区', 3);

使用PostgreSQL的WITH查询检索ID为 5 以及以上的所有父节点:

WITH RECURSIVE r AS
  (SELECT *
   FROM area
   WHERE id = 5
     UNION   ALL
     SELECT area.*
     FROM area,
          r WHERE area.id = r.fatherid )
SELECT *
FROM r
ORDER BY id;

结果:

postgresql中的with查询_第3张图片

使用PostgreSQL的WITH查询检索ID为 4 以及以上的所有父节点:

WITH RECURSIVE r AS
  (SELECT *
   FROM area
   WHERE id = 4
     UNION   ALL
     SELECT area.*
     FROM area,
          r WHERE area.id = r.fatherid )
SELECT *
FROM r
ORDER BY id;

结果:

postgresql中的with查询_第4张图片

       在处理递归查询时,务必确保查询的递归部分最终不会返回元组,否则查询将无限循环。有时候,使用UNION代替UNION ALL可以通过丢弃前面重复输出的行来实现这一点。然而,循环通常不涉及完全重复的输出行:可能需要只检查一个或几个字段,以查看以前是否达到了相同的点。处理这种情况的标准方法是计算已访问值的数组。递归查询求值算法以广度优先的搜索顺序产生输出。

你可能感兴趣的:(PostgreSQL)