mysql 树型表 通过儿子节点找所有父级的方法

这篇博客探讨了如何在数据库中进行递归查询以查找父级节点。通过创建一个名为`treetable`的表并插入数据,然后使用一个递归SQL查询来寻找指定ID的父节点。这个查询方法对于处理层次结构数据非常有用,特别是在需要追溯层级关系的场景下。

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

-- 构造测试数据2
CREATE TABLE `treetable` (
`id` int NOT NULL ,
`name` varchar(50) NOT NULL ,
`parid` int NOT NULL ,
PRIMARY KEY (`id`)
)
;




insert into treetable
select 1,'1',0 union all
select 2,'1-1',1 union all
select 3,'1-1-1',2 union all
select 4,'1-1-1-1',3  union all
select 5,'1-1-1-1-1',
-- 递归找父亲
select * from 
(select id,name,if(id = (select parid from treetable where id=  @a),@a := id,0) as hassum from treetable,(select @a := 4) as t1 order by parid desc ) as t
where  t.hassum !=0;
在处理树形数据结构时,`Spark SQL` 并不像传统的关系数据库(如 MySQL 或 PostgreSQL)那样内置了对递归查询的支持。然而,我们仍然可以利用 `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、付费专栏及课程。

余额充值