`
sdu_wizard
  • 浏览: 99691 次
  • 性别: Icon_minigender_1
  • 来自: 亚特兰蒂斯
社区版块
存档分类
最新评论

记Mysql中递归查询的egg ache经历

阅读更多
Mysql中针对树形结构,查找一个节点的所有孩子(包括孙子)节点,及查找一个节点的所有祖先节点。

表结构:
CREATE TABLE `myboard_group` (
  `mygroup_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `mygroup_name` varchar(64) NOT NULL,
  `parent_id` int(11) unsigned NOT NULL DEFAULT '0',
  `create_time` datetime NOT NULL,
  `comment` varchar(256) DEFAULT NULL,
  `has_child` int(11) unsigned DEFAULT '0',
  PRIMARY KEY (`mygroup_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;




由于mysql里没有oracle中的start with …connnect by…这种查询树形结构的便捷方法,所以只能自己想办法了。

思路参照网上的方法,写一个存储过程,采用一个表来存储中间数据。

DROP PROCEDURE
IF EXISTS getGroupChildren;

CREATE PROCEDURE getGroupChildren (IN parent_idd INT)
BEGIN
	DECLARE
		lev INT;

DECLARE
	child_count INT;

SET lev = 1;

SET child_count = 0;

DROP TABLE
IF EXISTS group_tmp1;

CREATE TABLE group_tmp1 (
	mygroup_id INT (11),
	mygroup_name VARCHAR (64),
	parent_id INT (11),
	`create_time` datetime,
	`comment` VARCHAR (256),
	levv INT
) engine=memory;

INSERT INTO group_tmp1 SELECT
	mygroup_id,
	mygroup_name,
	parent_id,
	`create_time`,
	`comment`,
	1
FROM
	` myboard_group`
WHERE
	parent_id = parent_idd;

SELECT
	count(1) INTO child_count
FROM
	` myboard_group`
WHERE
	parent_id = parent_idd;

WHILE child_count > 0 DO

SET lev = lev + 1;

INSERT INTO group_tmp1 SELECT
	t.mygroup_id,
	t.mygroup_name,
	t.parent_id,
	t.`create_time`,
	t.`comment`,
	lev
FROM
	` myboard_group` t
JOIN group_tmp1 a ON t.parent_id = a.mygroup_id
AND a.levv = lev - 1;

SELECT
	count(1) INTO child_count
FROM
	` myboard_group` t
JOIN group_tmp1 a ON t.parent_id = a.mygroup_id
AND a.levv = lev - 1;

END
WHILE;

SELECT
	*
FROM
	group_tmp1;

DROP TABLE group_tmp1;

END;


调用该存储过程
CALL getGroupChildren (1);

结果



问题来了…
这个方案的思路比较明确,在存储过程中采用一个“临时表”,一层一层的将孩子节点的数据取出来依次放入该表,最后达到取出整棵树的目的,但是,问题出现了,就出在这个“临时表”上。Mysql中在一次查询中只能访问临时表(TEMPORARY TABLE)一次,而这里调用一次存储过程需要访问多次,临时表显然已不能满足需求。如果改为采用普通的永久表,在并发访问的情况下又有可能产生数据冲突(虽然可以采用向该表里加一个字段写入该次访问id,查询时按访问id查询的方式避免这个问题),所以最后只能采用上面看到的内存表(创建表时加engine=memory),勉强可以满足要求(Mysql中临时表可以单独授权访问权限,而把内存表的访问权限跟普通表划在了一起,所以只能将普通表的访问权限放开给该用户,带来了安全隐患)。

查找一个节点的所有祖先节点的实现如下:

DROP PROCEDURE
IF EXISTS getGroupAncestor;

CREATE PROCEDURE getGroupAncestor (IN child_idd INT)
BEGIN
	DECLARE
		lev INT; 

DECLARE
	father_id
 INT;

SET lev = 1;

SET father_id = 1;

DROP TABLE
IF EXISTS group_tmp2;

CREATE TABLE group_tmp2 (
	mygroup_id INT (11),
	mygroup_name VARCHAR (64),
	parent_id INT (11),
	`create_time` datetime,
	`comment` VARCHAR (256),
	levv INT
) ENGINE=memory;

INSERT INTO group_tmp2 SELECT
	t.mygroup_id,
	t.mygroup_name,
	t.parent_id,
	t.`create_time`,
	t.`comment`,
	1
FROM
	` myboard_group` t
WHERE EXISTS (select 1 from ` myboard_group` m where m.mygroup_id=child_idd and m.parent_id=t.mygroup_id);

SELECT
	t.mygroup_id INTO father_id
FROM
	` myboard_group` t
WHERE EXISTS (select 1 from ` myboard_group` m where m.mygroup_id=child_idd and m.parent_id=t.mygroup_id);

WHILE father_id > 0 DO

SET lev = lev + 1;

INSERT INTO group_tmp2 SELECT
	t.mygroup_id,
	t.mygroup_name,
	t.parent_id,
	t.`create_time`,
	t.`comment`,
	lev
FROM
	` myboard_group` t
JOIN group_tmp2 a ON a.parent_id=t.mygroup_id
AND a.levv = lev - 1;

SELECT
	t.parent_id INTO father_id
FROM
	` myboard_group` t
JOIN group_tmp2 a ON a.parent_id=t.mygroup_id
AND a.levv = lev - 1;

END WHILE;

SELECT
	*
FROM
	group_tmp2;

DROP TABLE if EXISTS  group_tmp2;

END;


调用该存储过程
CALL getGroupAncestor (6);



结果



我觉得,在mysql里递归查询肯定还有更好的办法的,只是我没找到,请大家多多指教。
  • 大小: 7.1 KB
  • 大小: 6.1 KB
  • 大小: 4.5 KB
分享到:
评论

相关推荐

    两种mysql递归tree查询效率-mysql递归tree

    ### 两种MySQL递归Tree查询效率分析 #### 一、背景与目的 在数据库操作中,经常需要处理具有层级结构的数据。例如,在处理组织结构、文件系统或是地区划分时,通常会采用递归的方式来查询这些层级关系。MySQL作为...

    MySQL递归查询

    MySQL 递归查询是指在 MySQL 中实现类似 Oracle Hierarchical Queries 的功能,用于查询树形结构中的所有子节点。由于 MySQL 目前还没有内置的递归查询功能,因此需要使用其他方法来实现。 第一种方法:使用函数来...

    MySQL实现递归查询的三种方式.rar

    在数据库管理中,递归查询是一种处理层次结构数据的有效方法,尤其在关系型数据库如MySQL中,递归查询可以帮助我们解决树形结构或有层级关系的数据检索问题。本资料主要探讨了MySQL中实现递归查询的三种常见方法:自...

    MySQL多种递归查询方法.docx

    ### MySQL多种递归查询方法详解 #### 一、Oracle中的递归查询方法 在Oracle数据库中,递归查询可以通过`...通过这些知识点的学习,不仅可以更好地理解递归查询的实现方法,还能掌握MySQL中用于字符串处理的强大工具。

    mysql递归查询.txt

    MySQL 中进行递归查询有两种常见的方式:一种是使用存储过程,另一种则是利用 SQL 函数来实现递归。 #### 二、通过存储过程实现递归查询 ##### 方法一:存储过程实现递归查询 **存储过程定义:** ```sql CREATE ...

    递归查询菜单树,支持mysql,oracle

    在MySQL中,我们可以使用自连接来实现递归查询。假设我们有一个名为`menus`的表,包含`id`(主键)、`parent_id`(父菜单ID)和`name`(菜单名)字段。可以编写一个如下的SQL查询: ```sql WITH RECURSIVE menu_...

    mysql 递归查询 树型结构 代码逻辑

    在MySQL中实现递归查询可以使用子查询或者自连接的方式。这里我们采用子查询的方式来构建递归逻辑。 ##### SQL 查询语句 假设表名为`sort_sw`,则可以通过以下SQL语句来获取所有层级的数据: ```sql WITH ...

    地区表MySql递归sql脚本

    地区表MySql递归sql脚本

    mysql递归查询.doc

    MySQL 递归查询是指在 MySQL 数据库中使用递归函数来实现树形结构数据的查询,例如部门表中某个部门的所有下属部分或者某个部分的所有上级部门。 在 MySQL 中实现递归查询需要使用自定义函数(Stored Function),...

    Mysql用递归的方式实现Rank功能

    Mysql用递归的方式实现Rank功能,比较简单.

    在ORACLE、MSSQL、MYSQL中树结构表递归查询的实现.pdf

    随着MYSQL版本的更新,尤其是MYSQL 8.0之后,开始支持公用表表达式(CTE)和WITH RECURSIVE语法,这使得在MYSQL中进行递归查询变得简单而直接。 在上述三种数据库系统中实现递归查询的示例代码通常如下: ORACLE中...

    mysql 树形结构查询

    mysql 树形结构查询 ...MySQL 中的树形结构查询可以使用存储过程来实现,并可以根据需要设置递归深度,以控制查询的深度。这种查询方式可以高效地查询树形结构的数据,并且可以提高查询效率和简化查询逻辑。

    mybatis递归查询菜单树

    在本示例中,"mybatis递归查询菜单树"是一个基于SpringBoot架构的应用,它演示了如何利用MyBatis进行递归查询来构建菜单树结构。此外,这个项目还集成了JTA(Java Transaction API)以支持分布式事务处理,并使用了...

    数据库设计之递归树查询

    本文将深入探讨如何通过递归查询来解决这类问题,并着重讲解使用`WITH`语句来实现递归查询的方法,适用于多种数据库系统,如MySQL、PostgreSQL、SQL Server等。 一、理解递归查询 递归查询是一种在数据库中遍历层级...

    DNS迭代查询和递归查询的区别.docx

    在 DNS 解析过程中,查询类型是一个关键概念,有两种主要的查询类型:迭代查询和递归查询。了解这两种查询类型的区别对于构建高效的 DNS infrastructure 是非常重要的。 递归查询 递归查询是最常见的发送到本地...

    PHP MYSQL 用递归写的留言本核心程序

    总的来说,这个“PHP MYSQL 用递归写的留言本核心程序”是一个很好的学习资源,它涵盖了Web开发中的基础技术,包括PHP编程、MySQL数据库操作以及递归算法的应用。理解并实践这样的程序,可以帮助开发者提升处理复杂...

    存储过程递归查询

    在数据库管理中,递归查询主要用于处理层级结构数据,如组织架构、产品分类等。递归查询可以方便地遍历多级关系,实现对无限层级的数据进行查询。 #### 二、SQL递归查询语法介绍 递归查询主要通过`WITH`子句实现,...

    一种MySQL数据库SQL递归查询的研究与实现.pdf

    总之,MySQL中实现SQL递归查询的关键在于理解和运用迭代的思想,通过巧妙地构造SQL语句,模拟递归过程,以应对各种层次结构数据的查询需求。虽然这需要更多的编程技巧和对数据库查询机制的深入理解,但通过这种方式...

    MyBatis之自查询使用递归实现 N级联动效果(两种实现方式)

    递归查询是指在一个查询中调用自身的查询,以便实现某些复杂的查询逻辑。在MyBatis中,我们可以使用递归查询来实现 N级联动效果。 两种实现方式 在本文中,我们将介绍两种实现 N级联动效果的方式:使用递归函数和...

Global site tag (gtag.js) - Google Analytics