关于postgresql递归查询显示树状结构数据

系统在开发过程,用到机构信息的树状结构,数据库表中关键的三个字段:机构ID,父级机构ID,机构名。

网上搜了很多的技术文单。需要按示例一个个去仔细判别各个表名、字段 以及关联关系,头痛。整理其SQL编写模式如下:

 -------------------------------------------------------------------------------

WITH RECURSIVE 递归查询名称 AS (
    --起始第一条记录,即根节点
    SELECT 数据唯一索引ID值, 父ID值, cast(数据唯一索引ID值 as text) AS 节点遍历路径  --节点遍历路径,第一个节点的值为数据,注意此处必须为文本字符串
    FROM 源始数据表名
    WHERE 开始节点的字段名=开始节点判定条件
    
    UNION ALL
    
    --下属节点数据记录
    SELECT 下属查询表别名.数据唯一索引ID值, 下属查询表别名.父ID值, CONCAT(递归查询名称别名.节点遍历路径, '>', 下属查询表别名.数据唯一索引ID值) 节点遍历路径
    FROM 源始数据表名 下属查询表别名
    
    --连接递归查询
    JOIN 递归查询名称 递归查询名称别名 ON 递归查询名称别名.数据唯一索引ID值 = 下属查询表别名.父ID值
)
SELECT * FROM 递归查询名称 order by 节点遍历路径;

 -------------------------------------------------------------------------------

以下是个具体的示例:

WITH RECURSIVE tree AS (
    SELECT brcid, brcname,parentbrc, cast(brcid as text) AS path1
    FROM btc_src_brcinfo
    WHERE parentbrc='800000000' --开始节点
    UNION ALL
    SELECT e.brcid, e.brcname,e.parentbrc, CONCAT(s.path1, '>', e.brcid) path1
    FROM btc_src_brcinfo e
    JOIN tree s ON s.brcid = e.parentbrc
)
SELECT * FROM tree order by path1;

查询显示结果如下:

在处理树形数据结构时,`Spark SQL` 并不像传统的关系型数据库(如 MySQLPostgreSQL)那样内置了对递归查询的支持。然而,我们仍然可以利用 `DataFrame API` 和 `SQL` 的功能通过迭代或自连接的方式模拟递归操作。 以下是基于 `Spark SQL` 实现递归查询树型结构的一种常见思路: --- ### 场景描述 假设有一张表记录了一个组织架构的数据,每条记录都有一个唯一的 ID 表示节点本身,并有一个 Parent_ID 指向其父级节点。我们需要从某个根节点出发,递归地查找所有子节点。 #### 示例数据: | id | parent_id | name | |------|-----------|----------| | 1 | null | 总经理 | | 2 | 1 | 部门A主管 | | 3 | 1 | 部门B主管 | | 4 | 2 | 员工甲 | | 5 | 2 | 员工乙 | 目标是从 "总经理" 开始查出所有的下属员工及其层级关系。 --- ### 解决方案 #### 步骤 1:加载数据到 DataFrame 首先将数据加载成 Spark 中的 DataFrame。 ```scala val df = spark.read.format("csv").option("header", "true").load("path/to/data") df.createOrReplaceTempView("org_chart") ``` #### 步骤 2:编写初始查询语句 我们可以先找到最顶层的所有节点(即 `parent_id IS NULL`),然后逐步向下遍历每一层的子节点。 ```sql WITH RECURSIVE Tree AS ( -- 初始条件:选择根节点 SELECT id, parent_id, name, 0 as level FROM org_chart WHERE parent_id IS NULL UNION ALL -- 迭代部分:加入下一层的子节点 SELECT c.id, c.parent_id, c.name, p.level + 1 FROM org_chart c INNER JOIN Tree p ON c.parent_id = p.id ) SELECT * FROM Tree ORDER BY level; ``` 由于 Spark SQL 目前并不直接支持 CTE (Common Table Expressions) 的递归语法,因此需要手动展开这个过程。 --- #### 手动实现递归逻辑(Scala 版本) 如果无法使用递归 SQL,则可以用程序化的方式来实现类似的功能: ```scala import org.apache.spark.sql.functions._ // 初始化为根节点 var treeDF = spark.sql("SELECT id, parent_id, name, CAST(0 AS INT) as level FROM org_chart WHERE parent_id IS NULL") // 定义最大深度限制 val maxDepth = 10 for(i <- 1 until maxDepth){ val nextLevelDF = spark.sql( s""" |SELECT c.id, c.parent_id, c.name, ${i} as level |FROM org_chart c |INNER JOIN (${treeDF}) t ON c.parent_id = t.id AND t.level = ${i - 1} """.stripMargin) // 如果找不到更多子节点则停止循环 if(nextLevelDF.count() == 0){ break() } // 将当前层级的结果合并进总结果集 treeDF = treeDF.union(nextLevelDF) } treeDF.orderBy(col("level")).show() ``` --- ### 结果展示 最终我们会得到一张包含每个节点以及它们所属层次的信息表格。 | id | parent_id | name | level | |------|-----------|------------|-------| | 1 | null | 总经理 | 0 | | 2 | 1 | 部门A主管 | 1 | | 3 | 1 | 部门B主管 | 1 | | 4 | 2 | 员工甲 | 2 | | 5 | 2 | 员工乙 | 2 | --- ### 注意事项 1. **性能优化**:对于非常深的树状结构,建议结合分区和广播变量等技术提升效率。 2. **数据完整性校验**:确保输入数据中不存在环路或其他异常情况导致死循环。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值