从概念到实践,带你掌握层次递归查询

本文分享自华为云社区《GaussDB数据库SQL系列-层次递归查询》,作者: Gauss松鼠会小助手2。

一、前言

层次递归查询是一种常见的SQL查询方式,特别是在一些层次化的数据存储结构中经常用到。本文主要以GaussDB数据库为实验平台,为大家讲解其使用方法。

二、GuassDB数据库层次递归查询概念

层次化结构可以理解为树状数据结构,由节点构成。举个简单的例子,如下图所示,由子节点向上查询根节点,或者由根节点遍历所有子节点:

递归查询是指查询中需要多次调用自身的查询方式。在递归查询中,查询会反复地递归进入到一个子查询中,直到查询得到满足条件的结果或遍历完整个查询范围。递归查询在数据库领域中有着重要的应用。方便数据处理,简化开发代码。

在GaussDB数据库中,递归查询可以通过使用 "select...start with...connect by...prior..." 和"WITH RECURSIVE"语法来实现。

三、GaussDB数据库层次递归查询实验示例

1、创建实验表

sql 复制代码
--创建实验表

CREATE TABLE area(

a_code VARCHAR(10)

,a_name VARCHAR(10)

,p_a_code VARCHAR(10)

,a_level INT);
--插入测试数据

INSERT INTO area VALUES('610000','陕西省','0','1');

INSERT INTO area VALUES('610100','西安市','610000','2');

INSERT INTO area VALUES('610101','市辖区','610100','3');

INSERT INTO area VALUES('610102','新城区','610100','3');

INSERT INTO area VALUES('610103','碑林区','610100','3');

INSERT INTO area VALUES('610104','莲湖区','610100','3');

INSERT INTO area VALUES('610111','灞桥区','610100','3');

INSERT INTO area VALUES('610112','未央区','610100','3');

INSERT INTO area VALUES('610113','雁塔区','610100','3');

INSERT INTO area VALUES('610114','阎良区','610100','3');

INSERT INTO area VALUES('610115','临潼区','610100','3');

INSERT INTO area VALUES('610116','长安区','610100','3');

INSERT INTO area VALUES('610122','蓝田县','610100','3');

INSERT INTO area VALUES('610124','周至县','610100','3');

INSERT INTO area VALUES('610125','鄠邑区','610100','3');

INSERT INTO area VALUES('610126','高陵区','610100','3');
--查看初始化结果

SELECT * FROM area;

2、sys_connect_by_path(col, separator)

描述:返回从根节点到当前行的连接路径。

参数:col为在路径中显示的列名,支持类型为CHAR/VARCHAR/NVARCHAR2/TEXT的列,参数separator为路径节点之间的分隔符。

返回值类型:text

示例:

sql 复制代码
-返回从根节点到当前行的连接路径

SELECT *, sys_connect_by_path(a_name, '-') FROM area start with a_code ='610000' connect by prior a_code = p_a_code;

3、connect_by_root(col)

描述:返回当前行的根节点值。

参数:col为输出列的名称。

返回值类型:即为所指定列col的数据类型。

示例:

sql 复制代码
--返回当前行的根节点值。

SELECT *, connect_by_root(a_name) FROM area start with a_code ='610000' connect by prior a_code = p_a_code;

4、WITH RECURSIVE

使用WITH RECURSIVE 关键字,:

sql 复制代码
--使用WITH RECURSIVE

WITH RECURSIVE t_area AS (

SELECT a_level,a_code,p_a_code,a_name, a_name ::varchar(50) AS path FROM area WHERE p_a_code = '0'

UNION ALL

SELECT t2.a_level+1,t1.a_code,t1.p_a_code, t1.a_name,CONCAT(t2.path, ',', t1.a_name) ::varchar(50) AS path FROM area t1 JOIN t_area t2 ON t1.p_a_code=t2.a_code

) SELECT * FROM t_area;

示例说明:这个查询使用了递归表达式来遍历省级行政区域关系。表达式使用了两个 SELECT 语句:第一个 SELECT 语句选取了所有父级代码为0的行政区域信息,并将它们添加到临时表 t_area 中。它们的层级选取初始化的a_level级,并且它们的路径被设置为它们的行政区名a_name。这个 SELECT 语句是递归查询的起点。第二个 SELECT 语句连接了 area表和t_area表。它选取了area表中所有具有父级行政区,并连接到t_area表中已经存在的行政区。对于每个连接的行,它们的层级是父级的层级加1,并且它们的路径是父级的路径加上逗号和它们自己的行政区。查询结果返回t_area表中所有的行政区信息。

("::varchar(50)" 是创建实验表时的字符长度不够,需要重新定义,二是两个SELECT 语句使用 UNION ALL 连接,需要保持类型长度一致)。

四、递归查询的优缺点

1、优点

递归查询能够简化应用程序代码,方便对数据结构的处理。在一些复杂的查询场景中,递归查询能够更快地得到结果。适用于各种类型的树形结构。

2、缺点

递归查询有时可能会产生很多次递归调用,导致性能下降。算法通常比其他方法更复杂,编写比较困难。不适合处理大型数据集。

五、总结

递归查询是一种非常实用的查询方法,在处理分层数据、树形数据等复杂查询场景中非常广泛。但是,在使用递归查询时需要注意一些问题:

• 必须合理控制递归深度,防止过度递归。

• 最好不要在递归查询中执行复杂的计算和组合操作,避免占用过多资源。

• 避免在递归查询中使用ORDER BY操作,这会大大降低性能。

• 在使用递归查询时,应该谨慎处理好死循环问题。

同样的, 在使用GaussDB等数据库时,只要正确合理的应用递归查询,就可以更好地提高查询效率和应用性能。

点击关注,第一时间了解华为云新鲜技术~

相关推荐
这个DBA有点耶5 小时前
DBA的AI助手:向量检索与NL2SQL入门
数据库·人工智能·postgresql·学习方法·dba
㳺三才人子5 小时前
初探 Flask
后端·python·flask·html
星栈独行5 小时前
我在 Rust 全栈项目里用 JWT 做无状态认证
开发语言·后端·rust·前端框架·开源·github·web
Java爱好狂.5 小时前
Java程序员体系化学习路线(2026最新版)
java·后端·java面试·java架构师·java程序员·java八股文·java学习路线
陈随易6 小时前
Redis 8.8发布,一定要更新
前端·后端·程序员
basketball6166 小时前
SQL 常用数据格式化操作方法总结
数据库·sql
装不满的克莱因瓶6 小时前
SpringBoot 如何将 lib 目录中jar包打包进最终的jar包里面
spring boot·后端·maven·jar·mvn
TE-茶叶蛋6 小时前
数据库-引用完整性(referential integrity)
数据库
IronMurphy6 小时前
MySQL拷打第二讲
数据库·mysql
ltl7 小时前
Transformer 原论文实验结果:为什么 28.4 BLEU 足以改写路线图
后端