Nếu bạn muốn có thể có một SELECT mà không gặp vấn đề về id cha phải thấp hơn id con, một hàm có thể được sử dụng. Nó cũng hỗ trợ nhiều con (như một cây nên làm) và cây có thể có nhiều đầu. Nó cũng đảm bảo ngắt nếu tồn tại một vòng lặp trong dữ liệu.
Tôi muốn sử dụng SQL động để có thể chuyển tên bảng / cột, nhưng các hàm trong MySQL không hỗ trợ điều này.
DELIMITER $$
CREATE FUNCTION `isSubElement`(pParentId INT, pId INT) RETURNS int(11)
DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE isChild,curId,curParent,lastParent int;
SET isChild = 0;
SET curId = pId;
SET curParent = -1;
SET lastParent = -2;
WHILE lastParent <> curParent AND curParent <> 0 AND curId <> -1 AND curParent <> pId AND isChild = 0 DO
SET lastParent = curParent;
SELECT ParentId from `test` where id=curId limit 1 into curParent;
IF curParent = pParentId THEN
SET isChild = 1;
END IF;
SET curId = curParent;
END WHILE;
RETURN isChild;
END$$
Ở đây, bảng test
phải được sửa đổi thành tên bảng thực và các cột (ParentId, Id) có thể phải được điều chỉnh cho tên thật của bạn.
Sử dụng :
SET @wantedSubTreeId = 3;
SELECT * FROM test WHERE isSubElement(@wantedSubTreeId,id) = 1 OR ID = @wantedSubTreeId;
Kết quả :
3 7 k
5 3 d
9 3 f
1 5 a
SQL để tạo thử nghiệm:
CREATE TABLE IF NOT EXISTS `test` (
`Id` int(11) NOT NULL,
`ParentId` int(11) DEFAULT NULL,
`Name` varchar(300) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into test (id, parentid, name) values(3,7,'k');
insert into test (id, parentid, name) values(5,3,'d');
insert into test (id, parentid, name) values(9,3,'f');
insert into test (id, parentid, name) values(1,5,'a');
insert into test (id, parentid, name) values(6,2,'o');
insert into test (id, parentid, name) values(2,8,'c');
CHỈNH SỬA: Đây là một mẹo nhỏ để tự mình kiểm tra. Nó buộc tôi phải thay đổi dấu phân cách bằng cách sử dụng dấu phân cách được xác định trước, nhưng nó hoạt động.