mysql查询无层级子级,如何查询MySql表以显示根及其子级。

UserID UserName ParentID TopID

1 abc Null Null

2 edf 1 1

3 gef 1 1

4 huj 3 1

5 jdi 4 1

6 das 2 1

7 new Null Null

8 gka 7 7

TopID and ParentID is from the userID

I Want to get a user record and its child and subchild record. Here userid1 is the root and its child are userid2 and userid 3. So If the user id is 1 I have to display all the records from userid 1 to userid 6 since all are child and SUbchild of the root. Similarly for userid3 I have to display userid3 and its child Userid 4 and Child of Userid 4 Userid5

if the userid is 3

output should be

Userid Username

3 gef

4 huj

5 jdi

I will know the userid and the topID so how can I do the query to acheive the above result.

SELECT UserID, UserName FROM tbl_User WHERE ParentID=3 OR UserID=3 And TopID=1;

By the above query I am able to display userid 3 and userid 4 I am not able to display userid 5, Kind of struck in it. Need help. Thanks

解决方案

It is technically possible to do recursive hierarchical queries in MySQL using stored procedures.

Here is one adapted to your scenario:

CREATE TABLE `user` (

`UserID` int(16) unsigned NOT NULL,

`UserName` varchar(32),

`ParentID` int(16) DEFAULT NULL,

`TopID` int(16) DEFAULT NULL,

PRIMARY KEY (`UserID`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO user VALUES (1, 'abc', NULL, NULL), (2, 'edf', 1, 1), (3, 'gef', 1, 1),

(4, 'huj', 3, 1), (5, 'jdi', 4, 1), (6, 'das', 2, 1), (7, 'new', NULL, NULL),

(8, 'gka', 7, 7);

DELIMITER $$

DROP PROCEDURE IF EXISTS `Hierarchy` $$

CREATE PROCEDURE `Hierarchy` (IN GivenID INT, IN initial INT)

BEGIN

DECLARE done INT DEFAULT 0;

DECLARE next_id INT;

-- CURSOR TO LOOP THROUGH RESULTS --

DECLARE cur1 CURSOR FOR SELECT UserID FROM user WHERE ParentID = GivenID;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

-- CREATE A TEMPORARY TABLE TO HOLD RESULTS --

IF initial=1 THEN

-- MAKE SURE TABLE DOESN'T CONTAIN OUTDATED INFO IF IT EXISTS (USUALLY ON ERROR) --

DROP TABLE IF EXISTS OUT_TEMP;

CREATE TEMPORARY TABLE OUT_TEMP (userID int, UserName varchar(32));

END IF;

-- ADD OURSELF TO THE TEMPORARY TABLE --

INSERT INTO OUT_TEMP SELECT UserID, UserName FROM user WHERE UserID = GivenID;

-- AND LOOP THROUGH THE CURSOR --

OPEN cur1;

read_loop: LOOP

FETCH cur1 INTO next_id;

-- NO ROWS FOUND, LEAVE LOOP --

IF done THEN

LEAVE read_loop;

END IF;

-- NEXT ROUND --

CALL Hierarchy(next_id, 0);

END LOOP;

CLOSE cur1;

-- THIS IS THE INITIAL CALL, LET'S GET THE RESULTS --

IF initial=1 THEN

SELECT * FROM OUT_TEMP;

-- CLEAN UP AFTER OURSELVES --

DROP TABLE OUT_TEMP;

END IF;

END $$

DELIMITER ;

CALL Hierarchy(3,1);

+--------+----------+

| userID | UserName |

+--------+----------+

| 3 | gef |

| 4 | huj |

| 5 | jdi |

+--------+----------+

3 rows in set (0.07 sec)

Query OK, 0 rows affected (0.07 sec)

CALL Hierarchy(1,1);

+--------+----------+

| userID | UserName |

+--------+----------+

| 1 | abc |

| 2 | edf |

| 6 | das |

| 3 | gef |

| 4 | huj |

| 5 | jdi |

+--------+----------+

6 rows in set (0.10 sec)

Query OK, 0 rows affected (0.10 sec)

Time to point out some caveats:

Since this is recursively calling a stored procedure, you need to increase the size of max_sp_recursion_depth, which has a max value of 255 (defaults to 0).

My results on a non-busy server with the limited test data (10 tuples of the user table) took 0.07-0.10 seconds to complete. The performance is such that it might be best to put the recursion in your application layer.

I didn't take advantage of your TopID column, so there might be a logic flaw. But the two test-cases gave me the expected results.

Disclaimer: This example was just to show that it can be done in MySQL, not that I endorse it in anyway. Stored Procedures, temporary tables and cursors are perhaps not the best way to do this problem.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值