所有
我在表中有三个字段,用于定义MySQL数据库版本5.0中存在的父子关系。表名是tb_Tree,它包含以下数据:
Table Name: tb_Tree
Id | ParentId | Name
--------------------
1 | 0 | Fruits
2 | 0 | Vegetables
3 | 1 | Apple
4 | 1 | Orange
5 | 2 | Cabbage
6 | 2 | Eggplant
如果指定了ParentId,如何编写查询以获取所有子节点。请注意,给出的表条目只是示例数据,它们可以包含更多行。 Oracle有一个“CONNECT BY PRIOR”子句,但我没有找到类似MySQL的东西。任何人都可以建议吗?
由于
答案 0 :(得分:10)
MySQL不支持递归查询,所以你必须这么做:
ParentID = X
其中X
是您的根目录的行。Id
值。Id
重复(1)。如果你知道最大深度,那么你可以将你的表连接到自己(使用LEFT OUTER JOIN)到最大可能的深度,然后清理NULL。
您还可以将树表示更改为nested sets。
答案 1 :(得分:2)
您还可以查看这个有趣的博客,该博客演示了如何在mysql中获得类似的结果
http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/
答案 2 :(得分:2)
这是一个老线程,但由于我在另一个论坛得到了问题,我想我会在这里添加它。对于这种情况,我创建了一个硬编码的存储过程来处理特定情况。这当然有一些缺点,因为并非所有用户都可以随意创建存储过程,但仍然如此。
考虑下表中包含节点和子节点:
CREATE TABLE nodes (
parent INT,
child INT
);
INSERT INTO nodes VALUES
( 5, 2), ( 5, 3),
(18, 11), (18, 7),
(17, 9), (17, 8),
(26, 13), (26, 1), (26,12),
(15, 10), (15, 5),
(38, 15), (38, 17), (38, 6),
(NULL, 38), (NULL, 26), (NULL, 18);
使用此表,以下存储过程将计算由提供的节点的所有后代组成的结果集:
delimiter $$
CREATE PROCEDURE find_parts(seed INT)
BEGIN
-- Temporary storage
DROP TABLE IF EXISTS _result;
CREATE TEMPORARY TABLE _result (node INT PRIMARY KEY);
-- Seeding
INSERT INTO _result VALUES (seed);
-- Iteration
DROP TABLE IF EXISTS _tmp;
CREATE TEMPORARY TABLE _tmp LIKE _result;
REPEAT
TRUNCATE TABLE _tmp;
INSERT INTO _tmp SELECT child AS node
FROM _result JOIN nodes ON node = parent;
INSERT IGNORE INTO _result SELECT node FROM _tmp;
UNTIL ROW_COUNT() = 0
END REPEAT;
DROP TABLE _tmp;
SELECT * FROM _result;
END $$
delimiter ;
答案 3 :(得分:1)
以下targetCompatibility
列出了所有植物及其if (strlen($a) > strlen($b))
return 1;
elseif (strlen($a) < strlen($b))
return -1;
else
return 0;
};
最多4个级别(当然您可以扩展级别):
select
然后您可以使用此查询来获取最终结果。例如,你可以得到所有的孩子#34; Fruits&#34;由下面的sql:
parentid
答案 4 :(得分:1)
可能会迟到。
使用MySQL8,您可以使用递归子句实现它。这是示例。
with recursive cte (id, name, parent_id) as (
select id,
name,
parent_id
from products
where parent_id = 19
union all
select p.id,
p.name,
p.parent_id
from products p
inner join cte
on p.parent_id = cte.id
)
select * from cte;
要获得更多帮助,请找到另一个thread,希望它会帮助某人。
答案 5 :(得分:0)
下面的存储过程订购一个表,该表的行具有前一个的后引用。注意第一步我将行复制到临时表 - 这些行符合某些条件。在我的情况下,这些是属于相同线性的行(在GPS导航中使用的道路)。业务领域并不重要。就我而言,我正在排序属于同一条道路的细分
DROP PROCEDURE IF EXISTS orderLocations; DELIMITER //
CREATE PROCEDURE orderLocations(_full_linear_code VARCHAR(11)) BEGIN
DECLARE _code VARCHAR(11);
DECLARE _id INT(4);
DECLARE _count INT(4);
DECLARE _pos INT(4);
DROP TEMPORARY TABLE IF EXISTS temp_sort;
CREATE TEMPORARY TABLE temp_sort (
id INT(4) PRIMARY KEY,
pos INT(4),
code VARCHAR(11),
prev_code VARCHAR(11)
);
-- copy all records to sort into temp table - this way sorting would go all in memory
INSERT INTO temp_sort SELECT
id, -- this is primary key of original table
NULL, -- this is position that still to be calculated
full_tmc_code, -- this is a column that references sorted by
negative_offset -- this is a reference to the previous record (will be blank for the first)
FROM tmc_file_location
WHERE linear_full_tmc_code = _full_linear_code;
-- this is how many records we have to sort / update position
SELECT count(*)
FROM temp_sort
INTO _count;
-- first position index
SET _pos = 1;
-- pick first record that has no prior record
SELECT
code,
id
FROM temp_sort l
WHERE prev_code IS NULL
INTO _code, _id;
-- update position of the first record
UPDATE temp_sort
SET pos = _pos
WHERE id = _id;
-- all other go by chain link
WHILE (_pos < _count) DO
SET _pos = _pos +1;
SELECT
code,
id
FROM temp_sort
WHERE prev_code = _code
INTO _code, _id;
UPDATE temp_sort
SET pos = _pos
WHERE id = _id;
END WHILE;
-- join two tables and return position along with all other fields
SELECT
t.pos,
l.*
FROM tmc_file_location l, temp_sort t
WHERE t.id = l.id
ORDER BY t.pos;
END;