mysql 递归查询语句_写一个mysql数据库的sql 递归查询,我现在有个能查询三级的,谁能帮我改为查询四级或五级的...

CREATE TABLE `tablea` (

`cid` int(10) unsigned NOT NULL,

`pid` int(10) unsigned NOT NULL,

`name` varchar(45) NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=gb2312

insert into `test`.`tablea`

(cid, pid, name)

values

(1 ,0 , '1 '),

(10 ,1 , '10 '),

(11 ,1 , '11 '),

(12 ,1 , '12 '),

(2 ,0 , '2 '),

(20 ,2 , '20 '),

(21 ,2 , '21 '),

(22 ,2 , '22 '),

(110, 10, '110'),

(120, 10, '120')

--

DELIMITER $$;

DROP PROCEDURE IF EXISTS `p_opt_getCount`$$

CREATE PROCEDURE `p_opt_getCount`(

in in_sql varchar(65532),

out out_count int)

BEGIN

-- get count from a select

DROP TABLE IF EXISTS xxx_t_count;

CREATE TEMPORARY TABLE xxx_t_count(num int) TYPE = HEAP;

set @sql = concat('insert xxx_t_count select count(*) from (', in_sql, ') a ');

PREPARE s1 FROM @sql;

EXECUTE s1;

DEALLOCATE PREPARE s1;

select num into out_count from xxx_t_count;

-- drop temporary table for releasing memory

DROP TABLE IF EXISTS xxx_t_count;

END$$

DELIMITER ;$$

-- 递归查找

DELIMITER $$;

DROP PROCEDURE IF EXISTS `p_opt_recursion`$$

CREATE PROCEDURE `p_opt_recursion`(

in in_table_name varchar(45), -- 目标表名

in child_column_name varchar(45), -- 子字段名

in parent_column_name varchar(45), -- 父字段名

in in_start_id int, -- 从那个值的父结点开始递归

in tmp_table_name varchar(45)) -- 自定义一个表名,用来得到递归的结果

BEGIN

DECLARE v_level INT default 0;

DECLARE v_count INT default 0;

DECLARE v_sql varchar(65532) default '';

-- temporary table doesn't support self-join

DROP TABLE IF EXISTS xxx_t_recursion;

CREATE TEMPORARY TABLE xxx_t_recursion(cid int, pid int, level int, INDEX `index_1`(`level`)) TYPE = HEAP;

DROP TABLE IF EXISTS xxx_t_recursion2;

CREATE TEMPORARY TABLE xxx_t_recursion2(cid int, pid int, level int, INDEX `index_1` (`level`)) TYPE = HEAP;

INSERT xxx_t_recursion(cid,pid,level) select in_start_id,in_start_id,v_level;

set v_sql = concat(' select a.',parent_column_name,' from ',in_table_name,' a, xxx_t_recursion b where a.',parent_column_name,' = b.cid and b.level = 0 ');

call p_opt_getCount(v_sql,v_count);

-- select v_count;

INSERT INTO xxx_t_recursion2 SELECT * FROM xxx_t_recursion;

WHILE v_count > 0 DO

SET v_level = v_level + 1;

set @sql = concat(' insert xxx_t_recursion(cid,pid,level) SELECT a.',child_column_name,',a.',parent_column_name,', ',v_level,' from ',in_table_name,' a, xxx_t_recursion2 b where a.',parent_column_name,' = b.cid and b.level = ',v_level,' - 1 ');

PREPARE s1 FROM @sql;

EXECUTE s1;

DEALLOCATE PREPARE s1;

set v_sql = concat(' select a.',parent_column_name,' from ',in_table_name,' a, xxx_t_recursion b where a.',parent_column_name,' = b.cid and b.level = ',v_level);

-- get v_sql record count

call p_opt_getCount(v_sql,v_count);

INSERT INTO xxx_t_recursion2 SELECT * FROM xxx_t_recursion;

END WHILE;

delete from xxx_t_recursion where level = 0;

SELECT * FROM xxx_t_recursion;

-- create temporary table named by tmp_table_name value

-- put the result in the new_temporary table

set @sql = concat('DROP TABLE IF EXISTS ',tmp_table_name);

PREPARE s1 FROM @sql;

EXECUTE s1;

DEALLOCATE PREPARE s1;

set @sql = concat('CREATE TEMPORARY TABLE ',tmp_table_name,'(cid int, pid int, level int, INDEX `index_1`(`level`)) TYPE = HEAP');

PREPARE s1 FROM @sql;

EXECUTE s1;

DEALLOCATE PREPARE s1;

set @sql = concat('insert ',tmp_table_name,' select * from xxx_t_recursion ');

PREPARE s1 FROM @sql;

EXECUTE s1;

DEALLOCATE PREPARE s1;

-- release memory

DROP TABLE IF EXISTS xxx_t_recursion;

DROP TABLE IF EXISTS xxx_t_recursion2;

/*set @sql = concat('select * from ',tmp_table_name);

PREPARE s1 FROM @sql;

EXECUTE s1;

DEALLOCATE PREPARE s1;*/

END$$

DELIMITER ;$$

-- 递归测试

DELIMITER $$;

DROP PROCEDURE IF EXISTS `zzz_test`$$

CREATE PROCEDURE `zzz_test`()

BEGIN

call p_opt_recursion('tablea','cid','pid',1,'xxx_table');

select * from xxx_table;

END$$

DELIMITER ;$$

----

call zzz_test();

2012年3月16日 09:41

c4b32610104e4aa0a99ec1cf83cb32ab.gif

3226

0

0

13

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值