对不起,我看到很多关于此的问题,但我并不了解更简单的方法。
我有: ID | parentId的|名称
答案 0 :(得分:1)
编辑:最初,我NULL
为我最顶层的节点parent_id
。那不对。它应该为零(我理解)。我发布了包含NULL
的原始插入语句,但在我工作时我必须将这些值更新为0.我在下面更正了我的测试数据....
这个:http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/
我做到了......这就是你想要的。
mysql> describe table_name;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| parent_id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
insert into table_name values (1, 0, 'one'); -- was parent_id null, was wrong, now zer
insert into table_name values (2, 1, 'one one');
insert into table_name values (3, 2, 'one one one');
insert into table_name values (4, 2, 'one one two');
insert into table_name values (5, 2, 'one one three');
insert into table_name values (6, 5, 'one one three one');
insert into table_name values (7, 1, 'one two');
insert into table_name values (8, 0, 'two'); -- was parent_id null, was wrong, now zero
insert into table_name values (9, 8, 'two one');
delimiter //
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE _id INT;
DECLARE _parent INT;
DECLARE _next INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;
SET _parent = @id;
SET _id = -1;
IF @id IS NULL THEN
RETURN NULL;
END IF;
LOOP
SELECT MIN(id)
INTO @id
FROM table_name
WHERE parent_id = _parent
AND id > _id;
IF @id IS NOT NULL OR _parent = @start_with THEN
SET @level = @level + 1;
RETURN @id;
END IF;
SET @level := @level - 1;
SELECT id, parent_id
INTO _id, _parent
FROM table_name
WHERE id = _parent;
END LOOP;
END
//
delimiter ;
SELECT CONCAT(REPEAT(' ', level - 1), CAST(hi.id AS CHAR)) AS treeitem,
parent_id, level, name
FROM (
SELECT hierarchy_connect_by_parent_eq_prior_id(id) AS id, @level AS level
FROM (
SELECT @start_with := 0,
@id := @start_with,
@level := 0
) vars, table_name
WHERE @id IS NOT NULL
) ho
JOIN table_name hi
ON hi.id = ho.id;
+---------------+-----------+-------+-------------------+
| treeitem | parent_id | level | name |
+---------------+-----------+-------+-------------------+
| 1 | 0 | 1 | one |
| 2 | 1 | 2 | one one |
| 3 | 2 | 3 | one one one |
| 4 | 2 | 3 | one one two |
| 5 | 2 | 3 | one one three |
| 6 | 5 | 4 | one one three one |
| 7 | 1 | 2 | one two |
| 8 | 0 | 1 | two |
| 9 | 8 | 2 | two one |
+---------------+-----------+-------+-------------------+
k ......如果你想从所有那些混乱中计算后代......你需要这样做:
select count(*)
from (select hierarchy_connect_by_parent_eq_prior_id(id) as id, @level as level
from (
select @start_with := 8, --> ID of top node you want to count under
@id := @start_with,
@level := 0
) vars, table_name
where @id is not null
) as x
where id is not null --> exclude that top node from the count