Mysql查找部门的下属部门(包括下属部门的下属部门)

现有部门表department,要求给出部门Id能够查出下属部门及下属部门的信息,department表有字段id,parent_id,department_name,level四个字段,现给出sql:

SELECT d2.* 
	FROM (
         SELECT t1.id,
                 IF(find_in_set(t1.parent_id, @pids) > 0, @pids := concat(@pids, ',', t1.id), 0) AS leafNodeId
         FROM (SELECT d1.id, d1.parent_id FROM department d1) t1,
		  (SELECT @pids := #{***给定部门id***} ) t2 
         ) t3 
         INNER JOIN department d2 ON d2.id = t3.id
WHERE t3.leafNodeId != 0

此sql只查询给定部门Id下的部门,不包含本部门,比如我查询id为3的部门,查询sql如下:
在这里插入图片描述

查询结果如下图所示:
在这里插入图片描述
下面详细解析sql:
“SELECT d1.id, d1.parent_id FROM department d1” 查询表中所有记录;
“SELECT @pids := 3” 指定要查询的Id为3;
“IF(find_in_set(t1.parent_id, @pids) > 0, @pids := concat(@pids, ‘,’, t1.id), 0) AS leafNodeId” 如果表中有记录的parent_id在 @pids中的话(即find_in_set(t1.parent_id, @pids) > 0),那么就将该记录的id拼接到@pids,leafNodeId为拼接后的@pids,否则leafNodeId为0,也就是说如果t1中有记录的id在@pids中那么下一次也将此id作为parent_id进行查找,如果不在@pids中则leafNodeId为0;
"WHERE t3.leafNodeId != 0"就是只查找该id下面及下面的下面部门;
"INNER JOIN department d2 ON d2.id = t3.id"只是为了更好的看查询结果

<think>嗯,用户让我介绍一下MySQL的CTE,也就是公共表表达式。首先,我需要确认自己对CTE的理解是否正确。CTE是在SQL查询中临时存在的结果集,可以在一个查询中被多次引用,通常用在WITH子句里。对吧? 然后,我应该从基本概念开始解释。CTE分为递归和非递归两种类型。非递归CTE主要用于简化复杂查询,提高可读性,而递归CTE则用于处理层次结构或树状数据,比如组织结构或者目录树。用户可能想知道这两种类型的具体应用场景。 接下来,要说明CTE的语法结构。用WITH关键字开始,然后给CTE命名,指定列名(可选),接着AS子句定义查询。如果是递归CTE,需要在定义中引用自身。这时候需要注意递归CTE必须包含终止条件,否则会进入无限循环。例如,用UNION ALL来连接初始查询和递归部分。 然后,可能需要举几个例子。比如,非递归CTE如何简化JOIN操作,或者递归CTE如何遍历树形结构。比如,员工层级表,通过递归CTE可以查询某个员工的所有下属。例子要简单明了,方便用户理解。 另外,需要提到CTE的优点,比如提高可读性、支持递归查询、可以替代视图或者子查询。同时也要指出它的限制,比如MySQL中递归CTE的深度限制,默认是1000次,可以通过cte_max_recursion_depth调整。可能用户在使用递归CTE时遇到最大递归次数错误,这时候需要提醒他们调整这个参数。 还要注意CTE的作用域,它只在当前查询中有效,不能跨查询使用。这可能和临时表或者子查询有所不同,用户需要清楚这一点。此外,CTE在MySQL中的版本支持情况,比如MySQL 8.0及以上才支持CTE,如果用户用的是旧版本,可能需要升级或者使用其他方法替代。 用户可能的疑问点包括:如何调试递归CTE,如何处理复杂的递归情况,或者如何优化CTE的性能。比如,在递归查询中使用UNION ALL和UNION的区别,或者如何避免递归中的重复数据。不过,如果用户是刚接触CTE,可能不需要太深入,但需要给出足够的提示,让他们知道有这些注意事项。 最后,总结一下CTE的适用场景和使用方法,帮助用户快速掌握基本用法,并鼓励他们在实际项目中尝试应用,比如处理分层数据或简化复杂查询结构。同时,提醒他们注意版本兼容性和递归深度的问题,避免常见错误。</think>### MySQL CTE(公共表表达式)分步详解 --- #### 1. **基本概念** - **CTE(Common Table Expression)** 是MySQL 8.0+引入的临时结果集,作用范围仅限于当前查询。 - 分为两种类型: - **非递归CTE**:简化复杂查询逻辑(如多层JOIN或子查询)。 - **递归CTE**:处理分层/树形数据(如组织结构、目录树)。 --- #### 2. **语法结构** ```sql WITH cte_name [(column_list)] AS ( -- 初始查询(非递归部分) SELECT ... UNION [ALL] -- 递归部分(仅递归CTE需要) SELECT ... FROM cte_name ... ) SELECT * FROM cte_name; ``` --- #### 3. **非递归CTE示例** **场景**:统计每个部门的平均工资及总人数。 ```sql WITH dept_stats AS ( SELECT department_id, AVG(salary) AS avg_salary, COUNT(*) AS employee_count FROM employees GROUP BY department_id ) SELECT d.department_name, s.avg_salary, s.employee_count FROM departments d JOIN dept_stats s ON d.department_id = s.department_id; ``` **作用**:将聚合逻辑与主查询分离,提高可读性。 --- #### 4. **递归CTE示例** **场景**:查询员工ID=101的所有下属层级。 **表结构**: ```sql CREATE TABLE employees ( employee_id INT PRIMARY KEY, employee_name VARCHAR(50), manager_id INT ); ``` **递归查询**: ```sql WITH RECURSIVE emp_hierarchy AS ( -- 初始查询:顶层员工 SELECT employee_id, employee_name, manager_id, 1 AS level FROM employees WHERE employee_id = 101 UNION ALL -- 递归部分:逐层向下查找 SELECT e.employee_id, e.employee_name, e.manager_id, eh.level + 1 FROM employees e JOIN emp_hierarchy eh ON e.manager_id = eh.employee_id ) SELECT * FROM emp_hierarchy; ``` **输出结果**: ``` +-------------+---------------+-------------+-------+ | employee_id | employee_name | manager_id | level | +-------------+---------------+-------------+-------+ | 101 | Alice | NULL | 1 | | 102 | Bob | 101 | 2 | | 103 | Charlie | 102 | 3 | +-------------+---------------+-------------+-------+ ``` --- #### 5. **CTE核心优势** | 特性 | 说明 | |---------------------|----------------------------------------------------------------------| | **代码复用** | 同一CTE可被多次引用,避免重复子查询 | | **逻辑分层** | 将复杂查询拆分为多个步骤,便于调试和维护 | | **递归能力** | 解决树形遍历、累积计算等传统SQL难以处理的问题 | | **优化器支持** | MySQL会对CTE进行优化,性能通常优于临时表 | --- #### 6. **注意事项** 1. **递归终止条件** - 必须确保递归部分最终返回空结果,否则触发 `Recursive query aborted after 1001 iterations` 错误。 - 修改递归深度(默认1000): ```sql SET SESSION cte_max_recursion_depth = 10000; ``` 2. **性能优化** - 递归CTE中避免使用`UNION`(去重开销),优先用`UNION ALL`。 - 对递归字段(如`manager_id`)建立索引。 3. **版本兼容性** - CTE仅支持MySQL 8.0+,低版本需改用存储过程或临时表。 --- #### 7. **适用场景** - **分层数据**:组织架构、评论树、文件目录。 - **累积计算**:路径分析(如社交网络关系链)。 - **数据预处理**:多步骤ETL中的中间结果暂存。 --- #### 8. **对比其他技术** | 技术 | 优点 | 缺点 | |-------------|-------------------------------|-------------------------------| | **CTE** | 无需物理存储,自动作用域管理 | 无法跨会话复用 | | **子查询** | 兼容所有MySQL版本 | 多层嵌套可读性差 | | **临时表** | 可跨多查询复用 | 需手动创建/清理,增加I/O开销 | --- 通过CTE,开发者能以更简洁的方式表达复杂查询逻辑,建议在实际项目中优先替代嵌套子查询或临时表方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值