AnalyticDB for PostgreSQL 6.0 新特性解析:Recursive CTE (Common Table Expressions)

简介: Recursive CTE (Common Table Expressions) 能够实现SQL的递归查询功能,一般用于处理逻辑上为层次化或树状结构的数据(如查询组织结构、物料清单等),方便对该类数据进行多级递归查询。

作者简介:陈毅能(苇度)毕业于中国科学院,曾任职于百度、微软亚洲研究院、华为、阿里巴巴等公司,专注于分布式数据库内核开发。

Recursive CTE (Common Table Expressions) 能够实现SQL的递归查询功能,一般用于处理逻辑上为层次化或树状结构的数据(如查询组织结构、物料清单等),方便对该类数据进行多级递归查询。与Oracle的CONNECT BY语法的功能类似。

在AnalyticDB for PostgreSQL 6.0版本中,Recursive CTE不再作为待验证特性,而是默认打开。可以通过参数gp_recursive_cte打开或关闭Recursive CTE,默认情况下,gp_recursive_cte是打开的。

show gp_recursive_cte;

 gp_recursive_cte
------------------
 on
(1 row)

例子:1到100求和

使用Recursive CTE可以完成一些普通SQL语句无法完成的功能。使用Recursive CTE后,SQL语句可以引用它自己的输出。首先来看一个例子,计算1、2、……、100的和。

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

 sum
------
 5050
(1 row)

上述例子中,CTE递归调用了自己,从而生成了1到100的序列,进而在主查询中进行求和。

Recursive CTE语法及执行逻辑

使用Recursive CTE的语法如下:

WITH RECURSIVE cte_name AS (
    non_recursive_term
  UNION [ ALL ]
    recursive_term
)
sql_statement;

在recursive_term的部分,Recursive CTE对自身进行自引用。其整体执行逻辑如下:

  • 执行non_recursive_term部分。如果是UNION,还需要执行一次去重。然后将数据作为本轮执行的结果,并将其结果放入一个临时工作表
  • 如果这个临时工作表非空,则循环执行如下步骤。如果这个临时工作表为空,则返回所有轮的执行结果
    (1)执行recursive_term部分。如果是UNION,需要去除重复数据,且要去除和之前结果重复的数据。然后将数据作为本轮执行的结果,并将其结果放入一个中间结果表

(2)将临时工作表的内容替换为中间结果表,并且清空中间结果表

在使用Recursive CTE的时候,需要确保执行结果是可收敛的,即总有一轮的执行结果为空,以结束循环,否则查询将出现无限循环。在前面1到100求和的例子中,有一个WHERE条件限制循环执行100步,数字达到100后因不满足WHERE条件,返回0行数据,循环终止,查询结束。

从上述执行逻辑看,Recursive CTE将对数据进行广度优先遍历。

例子:通过省市上下级关系表查询

建立省市上下级关系表:

CREATE TABLE city_relation
(
    id int           -- 当前省市id
  , parent_id int    -- 上级省市id
  , name varchar(10) -- 当前省市名称
);

插入省市关系数据:

INSERT INTO city_relation values( 2,  NULL, '浙江省');
INSERT INTO city_relation values( 1,  NULL, '广东省');
INSERT INTO city_relation values( 3,  2,    '衢州市');
INSERT INTO city_relation values( 4,  2,    '杭州市');
INSERT INTO city_relation values( 5,  2,    '湖州市');
INSERT INTO city_relation values( 6,  2,    '嘉兴市');
INSERT INTO city_relation values( 7,  2,    '宁波市');
INSERT INTO city_relation values( 8,  2,    '绍兴市');
INSERT INTO city_relation values( 9,  2,    '台州市');
INSERT INTO city_relation values(10,  2,    '温州市');
INSERT INTO city_relation values(11,  2,    '丽水市');
INSERT INTO city_relation values(12,  2,    '金华市');
INSERT INTO city_relation values(13,  2,    '舟山市');
INSERT INTO city_relation values(14,  4,    '上城区');
INSERT INTO city_relation values(15,  4,    '下城区');
INSERT INTO city_relation values(16,  4,    '拱墅区');
INSERT INTO city_relation values(17,  4,    '余杭区');
INSERT INTO city_relation values(18, 11,    '金东区');
INSERT INTO city_relation values(19,  1,    '广州市');
INSERT INTO city_relation values(20,  1,    '深圳市');

查询浙江省及其下属城市列表:

WITH RECURSIVE cities AS 
( 
    SELECT id, name, parent_id, name::text as path FROM city_relation WHERE id=2
  UNION ALL
    SELECT t.id, t.name, t.parent_id, c.path || '>' || t.name as path
    FROM city_relation t JOIN cities c ON t.parent_id = c.id
)
SELECT id, name, path FROM cities;

查询结果:

  id |  name  |         path
----+-------+----------------------
  2 | 浙江省 | 浙江省
 13 | 舟山市 | 浙江省>舟山市
 11 | 丽水市 | 浙江省>丽水市
 10 | 温州市 | 浙江省>温州市
  9 | 台州市 | 浙江省>台州市
  6 | 嘉兴市 | 浙江省>嘉兴市
  5 | 湖州市 | 浙江省>湖州市
 12 | 金华市 | 浙江省>金华市
  8 | 绍兴市 | 浙江省>绍兴市
  7 | 宁波市 | 浙江省>宁波市
  4 | 杭州市 | 浙江省>杭州市
  3 | 衢州市 | 浙江省>衢州市
 18 | 金东区 | 浙江省>丽水市>金东区
 17 | 余杭区 | 浙江省>杭州市>余杭区
 14 | 上城区 | 浙江省>杭州市>上城区
 15 | 下城区 | 浙江省>杭州市>下城区
 16 | 拱墅区 | 浙江省>杭州市>拱墅区
(17 rows)

引用

[1] https://gpdb.docs.pivotal.io/6-0/relnotes/gpdb-60-release-notes.html
[2] https://gpdb.docs.pivotal.io/6-0/admin_guide/query/topics/CTE-query.html
[3] https://blog.csdn.net/zengshaotao/article/details/84753796 (版权不明,互联网上可找到的发表最早的一篇)

相关实践学习
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
相关文章
|
11月前
|
存储 SQL 监控
数据中台架构解析:湖仓一体的实战设计
在数据量激增的数字化时代,企业面临数据分散、使用效率低等问题。数据中台作为统一管理与应用数据的核心平台,结合湖仓一体架构,打通数据壁垒,实现高效流转与分析。本文详解湖仓一体的设计与落地实践,助力企业构建统一、灵活的数据底座,驱动业务决策与创新。
|
9月前
|
存储 人工智能 关系型数据库
阿里云AnalyticDB for PostgreSQL 入选VLDB 2025:统一架构破局HTAP,Beam+Laser引擎赋能Data+AI融合新范式
在数据驱动与人工智能深度融合的时代,企业对数据仓库的需求早已超越“查得快”这一基础能力。面对传统数仓挑战,阿里云瑶池数据库AnalyticDB for PostgreSQL(简称ADB-PG)创新性地构建了统一架构下的Shared-Nothing与Shared-Storage双模融合体系,并自主研发Beam混合存储引擎与Laser向量化执行引擎,全面解决HTAP场景下性能、弹性、成本与实时性的矛盾。 近日,相关研究成果发表于在英国伦敦召开的数据库领域顶级会议 VLDB 2025,标志着中国自研云数仓技术再次登上国际舞台。
1044 1
|
Cloud Native 关系型数据库 OLAP
云原生数据仓库产品使用合集之阿里云云原生数据仓库AnalyticDB PostgreSQL版的重分布时间主要取决的是什么
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。
|
运维 Cloud Native 关系型数据库
云原生数据仓库产品使用合集之原生数据仓库AnalyticDB PostgreSQL版如果是列存表的话, adb支持通过根据某个字段做upsert吗
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。
|
SQL 关系型数据库 数据库
PostgreSQL数据库报错 ERROR: multiple default values specified for column "" of table "" 如何解决?
PostgreSQL数据库报错 ERROR: multiple default values specified for column "" of table "" 如何解决?
1120 59
|
监控 数据挖掘 OLAP
深入解析:AnalyticDB中的高级查询优化与性能调优
【10月更文挑战第22天】 AnalyticDB(ADB)是阿里云推出的一款实时OLAP数据库服务,它能够处理大规模的数据分析任务,提供亚秒级的查询响应时间。对于已经熟悉AnalyticDB基本操作的用户来说,如何通过查询优化和性能调优来提高数据处理效率,是进一步提升系统性能的关键。本文将从个人的角度出发,结合实际经验,深入探讨AnalyticDB中的高级查询优化与性能调优技巧。
849 4
|
存储 SQL 缓存
AnalyticDB 实时数仓架构解析
AnalyticDB 是阿里云自研的 OLAP 数据库,广泛应用于行为分析、数据报表、金融风控等应用场景,可支持 100 trillion 行记录、10PB 量级的数据规模,亚秒级完成交互式分析查询。本文是对 《 AnalyticDB: Real-time OLAP Database System at Alibaba Cloud 》的学习总结。
512 1
|
存储 SQL 分布式计算
湖仓一体架构深度解析:构建企业级数据管理与分析的新基石
【10月更文挑战第7天】湖仓一体架构深度解析:构建企业级数据管理与分析的新基石
1203 1
|
分布式计算 安全 OLAP
7倍性能提升|阿里云AnalyticDB Spark向量化能力解析
AnalyticDB Spark如何通过向量化引擎提升性能?
|
运维 Cloud Native 关系型数据库
云原生数据仓库AnalyticDB产品使用合集之PostgreSQL版是否直接支持实时物化视图
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。
395 3

相关产品

  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多