关键词:mysql树查询,mysql递归查询

转自:http://www.cnblogs.com/c-h-y/p/9420726.html

之前一直用的是Oracle,对于树形查询可以使用start with ... connect by

select * from menu start with id='130000' connect by id = prior parent_id;

没错,这是Oracle所支持的

现在公司用的是mysql,对于这种查询方式只能通过sql语句实现了

语言都是相通的,何况sql呢

mysql随没有自带的语法支持,不过可以通过创建函数来实现递归查询。

直接上sql语句

create table `nodelist` (
`id` int (11),
`nodecontent` varchar (300),
`pid` int (11)
);
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('1','a',NULL);
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('2','b','1');
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('3','c','1');
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('4','d','2');
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('5','e','3');
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('6','f','3');
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('7','g','5');
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('8','h','7');
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('9','i','8');
insert into `nodelist` (`id`, `nodecontent`, `pid`) values('10','j','8');

之后创建一个函数

 

--根据父节点求出所有儿子节点
delimiter $$
DROP FUNCTION IF EXISTS `getChild`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `getChild`(rootId INT) RETURNS VARCHAR(1000) CHARSET utf8
BEGIN
DECLARE ptemp VARCHAR(1000);
DECLARE ctemp VARCHAR(1000);
SET ptemp = '#';
SET ctemp =CAST(rootId AS CHAR);
WHILE ctemp IS NOT NULL DO
SET ptemp = CONCAT(ptemp,',',ctemp);
SELECT GROUP_CONCAT(id) INTO ctemp FROM nodelist
WHERE FIND_IN_SET(pid,ctemp)>0;
END WHILE;
END$$
DELIMITER ; 如果报错:
  错误:This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de
  解决:set global log_bin_trust_function_creators=TRUE;
这是我们开启了bin-log, 我们就必须指定我们的函数是否是
1 DETERMINISTIC 不确定的
2 NO SQL 没有SQl语句,当然也不会修改数据
3 READS SQL DATA 只是读取数据,当然也不会修改数据
4 MODIFIES SQL DATA 要修改数据
5 CONTAINS SQL 包含了SQL语句 其中在function里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。如果我们开启了 bin-log, 我们就必须为我们的function指定一个参数。 在MySQL中创建函数时出现这种错误的解决方法:
set global log_bin_trust_function_creators=TRUE;

-- 测试使用

SELECT * FROM nodelist WHERE FIND_IN_SET(id, getChild(3))

-- 根据该节点获取所有父节点
delimiter $$
DROP FUNCTION IF EXISTS `getParentId`$$
CREATE DEFINER=`test1`@`localhost` FUNCTION `getParentId`(rootId INT) RETURNS VARCHAR(1000) CHARSET utf8
BEGIN
DECLARE ptemp VARCHAR(1000);
DECLARE ctemp VARCHAR(1000);
SET ptemp = '#';
SET ctemp =CAST(rootId AS CHAR);
WHILE ctemp IS NOT NULL DO
SET ptemp = CONCAT(ptemp,',',ctemp);
SELECT GROUP_CONCAT(pid) INTO ctemp FROM nodelist
WHERE FIND_IN_SET(id,ctemp)>0;
END WHILE;
return ptemp;
END$$
DELIMITER ; -- 测试实用
SELECT * FROM nodelist WHERE FIND_IN_SET(id, getParentId(3))
  


-- 获取该节点相关的所有父节点子节点
delimiter $$
DROP FUNCTION IF EXISTS `getAllNode`$$
CREATE DEFINER=`test1`@`localhost` FUNCTION `getAllNode`(rootId INT) RETURNS VARCHAR(1000) CHARSET utf8
BEGIN
DECLARE ptemp VARCHAR(1000);
DECLARE ctemp VARCHAR(1000);
SET ptemp = '#';
SET ctemp =CAST(rootId AS CHAR);
WHILE ctemp IS NOT NULL DO
SET ptemp = CONCAT(ptemp,',',ctemp);
SELECT GROUP_CONCAT(id) INTO ctemp FROM nodelist
WHERE FIND_IN_SET(pid,ctemp)>0;
END WHILE; SET ctemp =CAST(rootId AS CHAR);
WHILE ctemp IS NOT NULL DO
SET ptemp = CONCAT(ptemp,',',ctemp);
SELECT GROUP_CONCAT(pid) INTO ctemp FROM nodelist
WHERE FIND_IN_SET(id,ctemp)>0;
END WHILE;
return ptemp; END$$
DELIMITER ; -- 测试验证
SELECT * FROM nodelist WHERE FIND_IN_SET(id, getAllNode(3))


上面难度相对比较大,再补充一个简单的自连接查询

SELECT t1.id,t1.nodecontent,t2.nodecontent parentnodecontent FROM nodelist t1
LEFT JOIN nodelist t2
ON t1.pid = t2.id

可以了。

  其他相关参考:

    

本例根据上述代码实现(但仅限非常正序的情况,否则会出问题)

--顺序查找所有子节点
select * from (
select *,if(find_in_set(pid,@p)>0,@p:=concat(@p,',',id),0) as childId from
(select * from nodelist order by id) t1 ,(select @p:=3) t2
) t
where t.childId!=0;
  
--倒序查找所有父节点
select * from (
select *,if(find_in_set(id,@p1)>0,@p1:=concat(@p1,',',pid),0) as childId,@p1 from
(select * from nodelist order by id desc ) t1 ,(select @p1:=3) t2
) t
where t.childId!=0;
  

  


  

  

借鉴 https://www.jianshu.com/p/f99665266bb1

里面用到的内置函数 https://baijiahao.baidu.com/s?id=1595349117525189591&wfr=spider&for=pc

你只要能想到的,都有对应的解决方式,幸运的是你该踩得一些坑别人实现给你填好了。

mysql树查询、递归查询的更多相关文章

  1. MySQL知识树-查询语句

    在日常的web应用开发过程中,一般会涉及到数据库方面的操作,其中查询又是占绝大部分的.我们不仅要会写查询,最好能系统的学习下与查询相关的知识点,这篇随笔我们就来一起看看MySQL查询知识相关的树是什么 ...

  2. 字符串的公共前缀对Mysql B+树查询影响回溯分析

        年前项目组接微信公众号. 上线之后,跟微信相关的用cid列的查询会话的SQL变慢了几十倍!思考这个问题思考了非常久.从出现以来一直是我心头的一个结.cid这一列是建了索引的,普通的cid列更新 ...

  3. 提高MySQL数据库查询效率的几个技巧(转载)

    [size=5][color=Red]提高MySQL数据库查询效率的几个技巧(转)[/color][/size]      MySQL由于它本身的小巧和操作的高效, 在数据库应用中越来越多的被采用.我 ...

  4. mysql的查询使用explain的讲解

    摘自:http://www.jb51.net/article/33736.htm 在 explain的帮助下,您就知道什么时候该给表添加索引,以使用索引来查找记录从而让select 运行更快.如果由于 ...

  5. MySQL简单查询详解-单表查询

    MySQL简单查询详解-单表查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查询的执行路径 一条SQL查询语句的执行过程大致如下图所示: 1>.客户端和服务端通过my ...

  6. MySql学习—— 查询性能优化 深入理解MySql如何执行查询

    本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...

  7. MySQL之查询性能优化(二)

    查询执行的基础 当希望MySQL能够以更高的性能运行查询时,最好的办法就是弄清楚MySQL是如何优化和执行查询的.MySQL执行一个查询的过程,根据图1-1,我们可以看到当向MySQL发送一个请求时, ...

  8. mysql数据库查询过程探究和优化建议

    查询过程探究 我们先看一下向mysql发送一个查询请求时,mysql做了什么? 如上图所示,查询执行的过程大概可分为6个步骤: 客户端向MySQL服务器发送一条查询请求 服务器首先检查查询缓存,如果命 ...

  9. mysql慢查询解析-linux命令

    使用mysqldumpslow 命令可以解析mysql慢查询日志,mysqldumpslow的参数如下: -s ,是按照任何方式排序,c.t.l.r分别是按照记录次数.时间.查询时间.返回的记录数 来 ...

随机推荐

  1. JS深度比较两个对象是否相等

    /** * 深度比较两个对象是否相等 * @type {{compare: compareObj.compare, isObject: (function(*=): boolean), isArray ...

  2. element隐藏组件滚动条scrollbar使用

    可使用 组件 <el-scrollbar></el-scrollbar> 设置 组件的样式 为 高度100% <el-scrollbar style="heig ...

  3. bzoj4530 [Bjoi2014]大融合 子树信息 LCT

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4530/ 题解 想要求出一条边的负载那么就是要求出一个点为根的时候的另一个点的子树大小. 又因为 ...

  4. 非父子组件通过事件传值-vue

    1.创建中央事件总线:额外的 new Vue()2.$emit 触发事件3.$on 监听事件 在使用组件的文件中: <template> <div> <x-test :b ...

  5. [原创]Laravel 基于redis队列的解析

    目录 参考链接 本文环境 为什么使用队列 Laravel 中的队列 分发任务 任务队列 Worker Last-Modified: 2019年5月10日11:44:18 参考链接 使用 Laravel ...

  6. 【leetcode】1147. Longest Chunked Palindrome Decomposition

    题目如下: Return the largest possible k such that there exists a_1, a_2, ..., a_k such that: Each a_i is ...

  7. mongdb 数据库

    安装mongdb 下载地址 https://www.runoob.com/mongodb/mongodb-window-install.html 检查 mongdb 是否安装成功which mongd ...

  8. Are We Ready for SDN? Implementation Challenges for Software-Defined Networks

    Name of article:Are We Ready for SDN?  Implementation Challenges for  Software-Defined Networks Orig ...

  9. mktime夏令时处理

    https://www.cnblogs.com/dongzhiquan/archive/2011/11/05/2237075.html 我们的最终目的是把字符串格式的时间转换为内部使用的“日历时间”, ...

  10. ScheduledThreadPoolExecutor 源码分析

    ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor 是能够在给定的延时之后.或周期性执行被提交任务的线程池 创建实例 /** * 线程池关闭 ...