mysql查询父id下所有子id,或者通过子id查询所有父id到最上层


前言

显示实现通过父id查询所有子id数据;第二部分同子id查询到最顶层根id(超级父id)


一、通过父id查询所有子id

1.数据库

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for t_parent
-- ----------------------------
DROP TABLE IF EXISTS `t_parent`;
CREATE TABLE `t_parent` (
  `id` bigint NOT NULL,
  `parent_id` bigint DEFAULT NULL,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_parent
-- ----------------------------
INSERT INTO `t_parent` VALUES ('1', '0', '张三');
INSERT INTO `t_parent` VALUES ('2', '0', '李四');
INSERT INTO `t_parent` VALUES ('11', '1', '张三儿子');
INSERT INTO `t_parent` VALUES ('21', '2', '李四儿子');
INSERT INTO `t_parent` VALUES ('111', '11', '张三孙子');

表数据如下:
在这里插入图片描述

2.查询语句

SELECT t3.*
FROM(SELECT t1.*,
            IF (FIND_IN_SET(parent_id, @pids) > 0,@pids := CONCAT(@pids, ',', id),'0') AS ischild
     FROM(SELECT t.id,t.parent_id,t.NAME
          FROM t_parent AS t
          ORDER BY t.id ASC) t1,
		 (SELECT @pids := '0') t2) t3
WHERE ischild != '0'

使用时候把t_parent 改成自己表,@pids := '0’这个是要查询的父id号

查询结果:
在这里插入图片描述

3.SQL解释

SELECT @pids := '0'

这是mysql中变量定义和赋值,“:=”就是赋值方式,这种赋值方式一般和select连用

FIND_IN_SET(parent_id, @pids) 

这个函数是:@pids中如果有parent_id的值,就返回对应的下标(下标从1开始)如下图
在这里插入图片描述

if(a > b, 1, 2)

这是mysql中if判断语句,语法是:如果a > b成立,结果就是1,否则就是2

CONCAT(@pids, ',', id)

CONCAT()是字符拼接函数
在这里插入图片描述

语句总结:

  1. 先把表中所有数据查询出来,并排好序(必须的)
  2. IF (FIND_IN_SET(parent_id, @pids) > 0,@pids := CONCAT(@pids, ',', id),'0') AS ischild 通过这条判断语句,将满足父子关系的字符赋值给ischild,不满足的将’0’赋值给ischild
  3. 再次查询,将ischild为’0’的筛选掉,剩下的就是满足要求的数据了

二、通过子id查询父id到根节点

1.查询语句

代码如下:

SELECT t3.*
FROM(SELECT t1.*,
            IF (FIND_IN_SET(id, @ids) > 0,@ids := CONCAT( parent_id,',', @ids),'0') AS isparent
     FROM(SELECT t.id,t.parent_id,t.NAME
          FROM t_parent AS t
          ORDER BY t.id DESC) t1,
		 (SELECT @ids := '111') t2) t3
WHERE t3.isparent != '0'

使用时候把t_parent 改成自己表,@ids := '111’这个是要查询的子id号,还有和查询父id不同的地方是ORDER BY t.id DESC,这里使用desc排序
查询结果:
在这里插入图片描述

总结

这个查询就是select查询,只不过通过多字查询,根据条件加上一列,作为新的表进行查询,最终得到想要的结果。
MySQL 5.7 提供了递归查询的功能,主要用于解决数据结构存在层级或者有相互引用关系的情况,例如家族树、论坛回复链等场景。通过递归查询,你可以编写 SQL 查询来遍历这样的复杂数据结构。 MySQL 的递归查询通常利用自连接 (self-join) 和 `RECURSIVE` 关键字来实现。`RECURSIVE` 关键字告诉 MySQL 这是一个递归查询,并允许查询结果继续与表自身匹配直至满足终止条件。 ### 示例: 假设我们有一个名为 `comments` 的表格,其中包含评论的信息,包括评论者ID (`commenter_id`)、目标评论ID (`target_comment_id`) 和评论时间 (`created_at`) 等字段。我们要找出所有与某个特定评论相关的直接和间接评论链。 ```sql SELECT c1.created_at, c1.commenter_id, c2.commenter_id AS parent_id FROM comments c1 JOIN comments c2 ON c1.target_comment_id = c2.id WHERE c1.parent_id = @start_comment_id -- @start_comment_id 是起始评论ID AND c1.id IN ( SELECT id FROM comments WHERE commenter_id = @start_comment_id -- 搜索起点评论的所有评论 ) UNION ALL SELECT c1.created_at, c1.commenter_id, c2.commenter_id AS parent_id FROM comments c1 JOIN comments c2 ON c1.target_comment_id = c2.id JOIN t ON t.id = c1.id -- 这里需要额外的关联,用于处理嵌套的递归查询 WHERE c1.parent_id IN ( SELECT parent_id FROM comments WHERE commenter_id = @start_comment_id -- 上层结果作为下一层搜索的起点 ) AND NOT EXISTS (SELECT * FROM comments WHERE id = c1.id AND parent_id IS NULL); -- 防止循环引用 ``` 请注意,这个例是为了展示递归查询的基本思路,实际实现时可能需要调整以适应具体数据库模式和需求。特别是自连接的数量和方式可能会根据实际情况有所变化。 ### 相关问题: 1. **如何优化递归查询的性能?** 递归查询可能导致大量数据操作,因此需要注意避免无限递归、设计合理的终止条件以及使用索引来加速查找过程。 2. **递归查询适用于哪些类型的场景?** 递归查询非常适合于数据存在层次结构或者相互引用关系的场景,比如文件系统、社交网络中的好友关系、评论系统等。 3. **递归查询是否可以应用于其他数据库管理系统?** 虽然 MySQL 支持递归查询通过 `RECURSIVE` 关键字实现,但在其他数据库管理系统如 PostgreSQL 或者 SQL Server 中,实现递归查询的方式可能有所不同。了解并学习其他 DBMS 提供的解决方案对于更广泛地应用递归查询至关重要。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值