mysql 递归查找父节点_MYSQL递归查询,根据子类ID查询所有父类(最全)
數據表結構
id??? name? parent_id
1??????? A??????? 0
2??????? B??????? 1
3??????? C??????? 1
4??????? D??????? 2
5??????? E??????? 4
6??????? F??????? 1
7??????? G??????? 1
注:parent_id 為0表示頂級父節點,即A是頂級父輩,沒有父節點
轉儲SQL表結構及數據
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for demo
-- ----------------------------
DROP TABLE IF EXISTS `demo`;
CREATE TABLE `demo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`parent_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of demo
-- ----------------------------
INSERT INTO `demo` VALUES ('1', 'A', '0');
INSERT INTO `demo` VALUES ('2', 'B', '1');
INSERT INTO `demo` VALUES ('3', 'C', '1');
INSERT INTO `demo` VALUES ('4', 'D', '2');
INSERT INTO `demo` VALUES ('5', 'E', '4');
INSERT INTO `demo` VALUES ('6', 'F', '1');
INSERT INTO `demo` VALUES ('7', 'G', '1');
需求:根據一個子ID,查詢所有父類
SQL如下:
SELECT T2.id, T2.name
FROM (
SELECT
@r AS _id,
(SELECT @r := parent_id FROM demo WHERE id = _id) AS parent_id,
@l := @l + 1 AS lvl
FROM
(SELECT @r := 5, @l := 0) vars,
demo h
WHERE @r <> 0) T1
JOIN demo T2
ON T1._id = T2.id
ORDER BY T1.lvl DESC結果如下
id? ? ? name
1? ? ? ? ?A
2? ? ? ? ?B
4? ? ? ? ?D
5? ? ? ? ?E
分析過程(答疑過程)
我使用將SQL語句拆分的方式,并展示每句SQL運行結果,讓各位可以看的更明白,以便于根據你自己的業務需求進行更改
1、先不管T2,先把T1的SQL抽出來看
SELECT
@r AS _id,
(SELECT @r := parent_id FROM demo WHERE id = _id) AS parent_id,
@l := @l + 1 AS lvl
FROM
(SELECT @r := 5, @l := 0) vars,
demo h
WHERE @r <> 0
運行結果
從這里可以看出,其實T1已經找出ID為5節點的所有父節點了,和T2(即demo表)進行左連接,只不過是為了根據Id獲取Name而已。而且還可以看出@l其實在整個SQL中并沒有什么作用,只是用來標識節點的等級,底級子節點的lvl為1,父節點lvl值越大表示越靠近頂級父節點,想象一下樹結構,你就明白了
2、搞明白@r := 5
SELECT @r := 5, @l := 0
運行結果
這里看出,其實@r,@l 就是一個變量而已,
作為變量自然你可以隨便起名,當然也可以隨便賦值,改成@a,@b也都是可以的
那這句SQL的意思就出來了,它表示給變量@r賦值,值為5,給@l賦值,值為0
因此,其實整個SQL的意思也明了了就是根據子ID5,查詢所有父類
3、搞懂變量@r 值如何變化
@r AS _id,
(SELECT @r := parent_id FROM demo WHERE id = _id) AS parent_id
根據MYSQL執行順序(在文章末尾處),SQL語句在執行時會先執行From,即會先執行上一步的賦值操作,因此這里的_id值為5,所以上面的SQL等同于如下SQL
SELECT @r := parent_id FROM demo WHERE id = 5
運行結果
這句SQL肯定沒人不會,但是有一個點很重要,它是整個執行過程的核心,就是@r := parent_id,它在查詢Id為5的節點的父Id時,把這個父Id同時賦給了變量@r。因此@r值改變了,它從5變為了4。
這個時候思路就很清晰了,只要我們設置限制條件,讓SQL在@r為0的時候結束循環就OK了
4、<>符號的含義
WHERE @r <> 0
這個就沒什么好說的了,<>符號在MYSQL中表示不等于,這就是我們在第四步中所說的限制條件,它限制了@r這個變量不能等于0。所以當@r不等于0時,SQL語句會根據子ID向上查詢父ID,又把父ID當做子ID賦值給@r,再次向上查詢,直至@r變量的值為0為止。
補充:如果業務不需要,可以完全可以去掉@l變量
SELECT ,
@a AS _id,
(SELECT @a := parent_id FROM demo WHERE id = _id) AS parent_id
FROM
(SELECT @a := 5) vars,
demo h
WHERE @a <> 0
運行結果
可以看出@l其實在整個SQL中并沒有什么作用,只是用來標識節點的等級,這也證實了我們上述第一步的關于@l的解釋
因為這個過程很類似于JAVA通過構造樹結構向上遞歸查詢的方式,所以這個SQL形式被很多人叫做MYSQL遞歸查詢
文章結尾
關于MYSQL的查詢順序
FROM
ON
JOIN
WHERE
GROUP By
CUBE|ROllUP
HAVING
SELECT
DISTINCT
ORDER BY
LIMIT
最先執行的是FROM操作,最后執行的是LIMIT操作。每個操作都會產生一個虛擬表,該虛擬表作為一個處理的輸入
總結
以上是生活随笔為你收集整理的mysql 递归查找父节点_MYSQL递归查询,根据子类ID查询所有父类(最全)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 怎样建立自己的网站(如何建立自己的认知体
- 下一篇: 新三板股票可以买吗 新三板股票可不可以买
