- 浏览: 388550 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (215)
- ubuntu (27)
- 虚拟机 (13)
- 数据库 (29)
- JAVA (40)
- 搜索 (23)
- 开发工具 (2)
- 产品 (2)
- 工具 (1)
- 应用服务器 (5)
- linux (17)
- log (1)
- 多线程 (3)
- 异常 (1)
- shell (6)
- 12306 ;互联网 (1)
- 持续集成&Hudson (4)
- js (1)
- JAVA OR-Map (1)
- 漏洞 (1)
- svn (1)
- MAVEN (3)
- 架构 (1)
- windows (1)
- json (1)
- web (3)
- jenkins (2)
- iptables (2)
- JAVA ssh (0)
- 项目管理 (1)
- tomcat (1)
- 安全 (1)
- 数据库 mysql (1)
- 性能 (1)
最新评论
-
sbwfgihc:
怎么用的啊,
<转>mysql 树查询语句 -
panghaoyu:
实现一个智能提示功能需要ajax、数据库、jsp/php、算法 ...
<转>Solr Suggest实现搜索智能提示 -
songsove:
请问您qq多少
solr 对拼音搜索和拼音首字母搜索的支持 -
panghaoyu:
实现一个智能提示功能需要ajax、数据库、jsp/php、算法 ...
<转>Solr Suggest实现搜索智能提示 -
norain1988:
这样就可以实现相关搜索了吗
solr 百度相关搜索类似功能的实现
原链接:http://blog.csdn.net/acmain_chm/article/details/4142971
在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点。但很遗憾,在MySQL的目前版本中还没有对应的功能。
在MySQL中如果是有限的层次,比如我们事先如果可以确定这个树的最大深度是4, 那么所有节点为根的树的深度均不会超过4,则我们可以直接通过left join 来实现。
但很多时候我们无法控制树的深度。这时就需要在MySQL中用存储过程来实现或在你的程序中来实现这个递归。本文讨论一下几种实现的方法。
样例数据:
树形图如下
方法一:利用函数来得到所有子节点号。
创建一个function getChildLst, 得到一个由所有子节点号组成的字符串.
使用我们直接利用find_in_set函数配合这个getChildlst来查找
优点: 简单,方便,没有递归调用层次深度的限制 (max_sp_recursion_depth,最大255) ;
缺点:长度受限,虽然可以扩大 RETURNS varchar(1000),但总是有最大限制的。
MySQL目前版本( 5.1.33-community)中还不支持function 的递归调用。
方法二:利用临时表和过程递归
创建存储过程如下。createChildLst 为递归过程,showChildLst为调用入口过程,准备临时表及初始化。
调用时传入结点
depth 为深度,这样可以在程序进行一些显示上的格式化处理。类似于oracle中的 level 伪列。sno 仅供排序控制。这样你还可以通过临时表tmpLst与数据库中其它表进行联接查询。
MySQL中你可以利用系统参数 max_sp_recursion_depth 来控制递归调用的层数上限。如下例设为12.
优点 : 可以更灵活处理,及层数的显示。并且可以按照树的遍历顺序得到结果。
缺点 : 递归有255的限制。
方法三:利用中间表和过程
(本方法由yongyupost2000提供样子改编)
创建存储过程如下。由于MySQL中不允许在同一语句中对临时表多次引用,只以使用普通表tmpLst来实现了。当然你的程序中负责在用完后清除这个表。
执行完后会产生一个tmpLst表,nLevel 为节点深度,sCort 为排序字段。
使用方法
优点 : 层数的显示。并且可以按照树的遍历顺序得到结果。没有递归限制。
缺点 : MySQL中对临时表的限制,只能使用普通表,需做事后清理。
以上是几个在MySQL中用存储过程比较简单的实现方法。
在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点。但很遗憾,在MySQL的目前版本中还没有对应的功能。
在MySQL中如果是有限的层次,比如我们事先如果可以确定这个树的最大深度是4, 那么所有节点为根的树的深度均不会超过4,则我们可以直接通过left join 来实现。
但很多时候我们无法控制树的深度。这时就需要在MySQL中用存储过程来实现或在你的程序中来实现这个递归。本文讨论一下几种实现的方法。
样例数据:
mysql> create table treeNodes -> ( -> id int primary key, -> nodename varchar(20), -> pid int -> ); Query OK, 0 rows affected (0.09 sec) mysql> select * from treenodes; +----+----------+------+ | id | nodename | pid | +----+----------+------+ | 1 | A | 0 | | 2 | B | 1 | | 3 | C | 1 | | 4 | D | 2 | | 5 | E | 2 | | 6 | F | 3 | | 7 | G | 6 | | 8 | H | 0 | | 9 | I | 8 | | 10 | J | 8 | | 11 | K | 8 | | 12 | L | 9 | | 13 | M | 9 | | 14 | N | 12 | | 15 | O | 12 | | 16 | P | 15 | | 17 | Q | 15 | +----+----------+------+ 17 rows in set (0.00 sec)
树形图如下
1:A +-- 2:B | +-- 4:D | +-- 5:E +-- 3:C +-- 6:F +-- 7:G 8:H +-- 9:I | +-- 12:L | | +--14:N | | +--15:O | | +--16:P | | +--17:Q | +-- 13:M +-- 10:J +-- 11:K
方法一:利用函数来得到所有子节点号。
创建一个function getChildLst, 得到一个由所有子节点号组成的字符串.
mysql> delimiter // mysql> mysql> CREATE FUNCTION `getChildLst`(rootId INT) -> RETURNS varchar(1000) -> BEGIN -> DECLARE sTemp VARCHAR(1000); -> DECLARE sTempChd VARCHAR(1000); -> -> SET sTemp = '$'; -> SET sTempChd =cast(rootId as CHAR); -> -> WHILE sTempChd is not null DO -> SET sTemp = concat(sTemp,',',sTempChd); -> SELECT group_concat(id) INTO sTempChd FROM treeNodes where FIND_IN_SET(pid,sTempChd)>0; -> END WHILE; -> RETURN sTemp; -> END -> // Query OK, 0 rows affected (0.00 sec) mysql> mysql> delimiter ;
使用我们直接利用find_in_set函数配合这个getChildlst来查找
mysql> select getChildLst(1); +-----------------+ | getChildLst(1) | +-----------------+ | $,1,2,3,4,5,6,7 | +-----------------+ 1 row in set (0.00 sec) mysql> select * from treeNodes -> where FIND_IN_SET(id, getChildLst(1)); +----+----------+------+ | id | nodename | pid | +----+----------+------+ | 1 | A | 0 | | 2 | B | 1 | | 3 | C | 1 | | 4 | D | 2 | | 5 | E | 2 | | 6 | F | 3 | | 7 | G | 6 | +----+----------+------+ 7 rows in set (0.01 sec) mysql> select * from treeNodes -> where FIND_IN_SET(id, getChildLst(3)); +----+----------+------+ | id | nodename | pid | +----+----------+------+ | 3 | C | 1 | | 6 | F | 3 | | 7 | G | 6 | +----+----------+------+ 3 rows in set (0.01 sec)
优点: 简单,方便,没有递归调用层次深度的限制 (max_sp_recursion_depth,最大255) ;
缺点:长度受限,虽然可以扩大 RETURNS varchar(1000),但总是有最大限制的。
MySQL目前版本( 5.1.33-community)中还不支持function 的递归调用。
方法二:利用临时表和过程递归
创建存储过程如下。createChildLst 为递归过程,showChildLst为调用入口过程,准备临时表及初始化。
mysql> delimiter // mysql> mysql> # 入口过程 mysql> CREATE PROCEDURE showChildLst (IN rootId INT) -> BEGIN -> CREATE TEMPORARY TABLE IF NOT EXISTS tmpLst -> (sno int primary key auto_increment,id int,depth int); -> DELETE FROM tmpLst; -> -> CALL createChildLst(rootId,0); -> -> select tmpLst.*,treeNodes.* from tmpLst,treeNodes where tmpLst.id=treeNodes.id order by tmpLst.sno; -> END; -> // Query OK, 0 rows affected (0.00 sec) mysql> mysql> # 递归过程 mysql> CREATE PROCEDURE createChildLst (IN rootId INT,IN nDepth INT) -> BEGIN -> DECLARE done INT DEFAULT 0; -> DECLARE b INT; -> DECLARE cur1 CURSOR FOR SELECT id FROM treeNodes where pid=rootId; -> DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; -> -> insert into tmpLst values (null,rootId,nDepth); -> -> OPEN cur1; -> -> FETCH cur1 INTO b; -> WHILE done=0 DO -> CALL createChildLst(b,nDepth+1); -> FETCH cur1 INTO b; -> END WHILE; -> -> CLOSE cur1; -> END; -> // Query OK, 0 rows affected (0.00 sec) mysql> delimiter ;
调用时传入结点
mysql> call showChildLst(1); +-----+------+-------+----+----------+------+ | sno | id | depth | id | nodename | pid | +-----+------+-------+----+----------+------+ | 4 | 1 | 0 | 1 | A | 0 | | 5 | 2 | 1 | 2 | B | 1 | | 6 | 4 | 2 | 4 | D | 2 | | 7 | 5 | 2 | 5 | E | 2 | | 8 | 3 | 1 | 3 | C | 1 | | 9 | 6 | 2 | 6 | F | 3 | | 10 | 7 | 3 | 7 | G | 6 | +-----+------+-------+----+----------+------+ 7 rows in set (0.13 sec) Query OK, 0 rows affected, 1 warning (0.14 sec) mysql> mysql> call showChildLst(3); +-----+------+-------+----+----------+------+ | sno | id | depth | id | nodename | pid | +-----+------+-------+----+----------+------+ | 1 | 3 | 0 | 3 | C | 1 | | 2 | 6 | 1 | 6 | F | 3 | | 3 | 7 | 2 | 7 | G | 6 | +-----+------+-------+----+----------+------+ 3 rows in set (0.11 sec) Query OK, 0 rows affected, 1 warning (0.11 sec)
depth 为深度,这样可以在程序进行一些显示上的格式化处理。类似于oracle中的 level 伪列。sno 仅供排序控制。这样你还可以通过临时表tmpLst与数据库中其它表进行联接查询。
MySQL中你可以利用系统参数 max_sp_recursion_depth 来控制递归调用的层数上限。如下例设为12.
mysql> set max_sp_recursion_depth=12; Query OK, 0 rows affected (0.00 sec)
优点 : 可以更灵活处理,及层数的显示。并且可以按照树的遍历顺序得到结果。
缺点 : 递归有255的限制。
方法三:利用中间表和过程
(本方法由yongyupost2000提供样子改编)
创建存储过程如下。由于MySQL中不允许在同一语句中对临时表多次引用,只以使用普通表tmpLst来实现了。当然你的程序中负责在用完后清除这个表。
delimiter // drop PROCEDURE IF EXISTS showTreeNodes_yongyupost2000// CREATE PROCEDURE showTreeNodes_yongyupost2000 (IN rootid INT) BEGIN DECLARE Level int ; drop TABLE IF EXISTS tmpLst; CREATE TABLE tmpLst ( id int, nLevel int, sCort varchar(8000) ); Set Level=0 ; INSERT into tmpLst SELECT id,Level,ID FROM treeNodes WHERE PID=rootid; WHILE ROW_COUNT()>0 DO SET Level=Level+1 ; INSERT into tmpLst SELECT A.ID,Level,concat(B.sCort,A.ID) FROM treeNodes A,tmpLst B WHERE A.PID=B.ID AND B.nLevel=Level-1 ; END WHILE; END; // delimiter ; CALL showTreeNodes_yongyupost2000(0);
执行完后会产生一个tmpLst表,nLevel 为节点深度,sCort 为排序字段。
使用方法
SELECT concat(SPACE(B.nLevel*2),'+--',A.nodename) FROM treeNodes A,tmpLst B WHERE A.ID=B.ID ORDER BY B.sCort; +--------------------------------------------+ | concat(SPACE(B.nLevel*2),'+--',A.nodename) | +--------------------------------------------+ | +--A | | +--B | | +--D | | +--E | | +--C | | +--F | | +--G | | +--H | | +--J | | +--K | | +--I | | +--L | | +--N | | +--O | | +--P | | +--Q | | +--M | +--------------------------------------------+ 17 rows in set (0.00 sec)
优点 : 层数的显示。并且可以按照树的遍历顺序得到结果。没有递归限制。
缺点 : MySQL中对临时表的限制,只能使用普通表,需做事后清理。
以上是几个在MySQL中用存储过程比较简单的实现方法。
发表评论
-
MYSQL--表分区、查看分区(转)
2014-12-15 21:50 730原文地址:http://blog.csdn ... -
<转>Mysql 慢查询和慢查询日志分析
2014-08-30 15:09 1269原链接:http://www.cnblogs.com/wrmf ... -
<转>MySQL锁定状态查看命令
2014-08-30 14:45 781原链接:http://blog.csdn.net/dc_726 ... -
<转>MySQL 事务没有提交导致 锁等待 Lock wait timeout exceeded
2014-08-30 14:39 1010原链接:http://my.oschina.net/jiaoy ... -
mysql函数
2014-05-27 11:20 573select curdate(); ... -
<转>从mysql到内存数据库的一些碎碎念
2014-04-24 15:30 1131原链接:http://blog.csdn.net/ty1921 ... -
修改mysql自增主键的初始值
2014-04-15 17:45 1076默认情况下ID是从1开始递增,如果要修改递增初始值,可在Mys ... -
<转> MySQL的经典用法----临时表与内存表
2014-04-09 15:47 851原链接:http://blog.csdn.net/feihon ... -
<转>Oracle中的软解析和硬解析
2014-04-02 14:10 963原链接:http://soft.chinabyte.com/d ... -
<转>mybatis防止sql注入
2014-03-28 10:19 896原链接:http://cs-css.iteye.com/blo ... -
mysql变相实现split
2014-03-10 18:01 826--按split取第2个字符分 ... -
mysql按拼音排序
2013-11-08 14:59 787select * from ac_operator order ... -
<转>深入mysql慢查询设置的详解
2013-10-12 10:22 646原链接:http://www.jb51.net/article ... -
<转>mysql对于大表(千万级),要怎么优化呢?
2013-10-11 18:01 739原链接:http://www.zhihu.com/questi ... -
<转>三个方法优化MySQL数据库查询
2013-10-11 17:18 575原链接:http://www.bitscn.com/pdb/m ... -
<转>详解MySQL中EXPLAIN解释命令
2013-10-11 16:56 756原链接:http://database.51c ... -
<转>mysql导入导出包括函数或者存储过程
2013-09-23 14:33 954mysql导入导出包括函数或者存储过程 1.mysql导出 ... -
mybatis技巧
2013-09-11 17:12 1266集合和in的表示 <delete id="d ... -
<转>mysql 树查询语句
2013-09-10 15:38 6559原链接:http://skudy.iteye.com/blog ... -
关于Oracle中split函数的实现以及函数递归的举例
2013-07-06 17:05 1012比如说把一个字符串A,B,C,D,E ...
相关推荐
在MySQL中,实现树状所有子节点的查询并非像Oracle那样可以直接使用Hierarchical Queries和`CONNECT BY`语句。然而,尽管MySQL不直接支持这样的功能,我们仍然可以通过其他方法来达到相同的效果。以下将详细介绍几种...
在Java中,通过递归方法我们可以轻松地实现从父节点获取所有子节点的功能,这对于构建树形结构的应用程序(如文件系统、组织结构或菜单系统)非常有用。理解并掌握递归是每个程序员必备的技能之一。
MySQL 递归查询是指在 MySQL 中实现类似 Oracle Hierarchical Queries 的功能,用于查询树形结构中的所有子节点。由于 MySQL 目前还没有内置的递归查询功能,因此需要使用其他方法来实现。 第一种方法:使用函数来...
在MySQL数据库中,处理树形结构的数据是一项常见的任务,特别是在...总之,通过自定义函数和递归查询,我们可以在MySQL中有效地查询树形结构的全部子项列表。在处理复杂的树形数据时,理解并掌握这种技术是非常重要的。
│ 8.2.2 树形数据深度排序处理示例(模拟单编号法).sql<br/>│ │ 8.2.2 树形数据深度排序处理示例(递归法).sql<br/>│ │ 8.2.3 查找指定节点的所有子节点的示例函数.sql<br/>│ │ 8.2.4 查找指定节点的所有父...
标题中的“根据子节点的金额向上汇总所有父节点的金额”是一个典型的树形结构数据处理问题,常见于组织架构、账目统计或者数据库层次结构的数据分析。这个问题涉及到的知识点包括但不限于: 1. **树形结构**:在...
在MySQL中,处理树状数据结构的查询是一个挑战,因为直到MySQL 8.0版本才引入了`WITH RECURSIVE`子句来支持递归查询。然而,在MySQL 5.0.94及更早版本中,如描述中提到的,没有内置的递归查询功能。为了遍历树状表的...
该函数首先检查`subCode`是否为空,如果为空则将其设为默认值`"9999999999999999"`,然后调用`getChildNodeParent`函数获取所有子节点,并将这些子节点再次传递给`getChildNode`进行深度遍历。 #### 非递归查询方法...
在MySQL中,递归查询通常用于处理层次结构的数据,如组织结构、菜单系统或类别树等。当数据的层级关系无法预知或者可能无限深时,传统的JOIN操作可能无法满足需求,此时就需要自定义函数来实现递归查询。本文将详细...
添加新节点时,我们需要找到合适的父节点并将其添加到子节点数组中;修改节点则涉及查找特定节点并更新其属性;删除节点则需要从数组中移除对应的节点,并更新所有受影响的子节点。 为了持久化这些数据,通常会将...
本项目"ztree树形结构+mysql完整"结合了ZTree的功能与MySQL数据库的使用,提供了一个完整的解决方案,包括数据存储、查询以及前端交互。 首先,ZTree的核心特性在于其丰富的API和可定制性。它支持动态加载、节点...
- **解释**: 从`id = '1001'`开始,递归查询所有子节点及其子节点的信息,包括起始节点本身。 - **第二种情况**: `PRIOR`在子节点端(向下递归),开始条件为父节点 - **SQL示例**: ```sql SELECT * FROM dept ...
本文将探讨如何使用SQL函数实现三种常见的递归查询:找到所有子节点、查找所有父节点以及面包屑导航数据。我们将通过一个名为`Region`的示例表来说明这些操作。 首先,我们需要一个基础的表结构,如`Category`或`...
在MySQL中处理这类数据时,可能会遇到需要查询某节点的所有子节点或父节点的情况。由于MySQL不直接支持像Oracle那样使用`START WITH ... CONNECT BY`的递归查询语法,我们需要采取其他策略来实现类似的功能。 在...
例如,通过查询所有`parent_id`为0的记录作为顶层节点,然后对每个节点递归查询其子节点,直到没有子节点为止。 2. **树状路径**:另一种方法是在表中添加一个额外的字段,如`path`,用来存储分类的完整路径。例如...
T树通过一种特殊的树形结构来优化多列索引的性能,但这种索引在MySQL中不常用,通常用在某些特定的数据库系统中,因为其维护成本和实现复杂度较高。 Hash Index是基于哈希表实现的索引,它通过哈希函数快速定位数据...
在进行树形查询时,我们通常会用到递归SQL查询或者利用数据库提供的特定功能,如Oracle的CONNECT BY,MySQL的WITH RECURSIVE,或者SQL Server的Hierarchical Queries。这些语法允许我们构建一个层次结构,从根节点...