Mysql 查詢指定節點的所有子節點

原文鏈接:https://www.zhoubotong.site/post/92.html

通常我們直接通過遞歸查詢來達到實現子節點數據獲取的需求,這裏不談存儲過程的實現,存儲過程普通賬號有權限限制,通常也不易於開發者維護,
這裏介紹下純mysql遞歸實現的方式:
測試數據可以通過之前的一篇文章來模擬。在正式介紹實現之前,我們先了解下幾個mysql實現涉及的相關知識點:

Mysql用戶變量

用戶變量無需聲明,直接賦值就行。用戶變量名不區分大小寫。名稱的最大長度爲64個字符。常用的賦值方式有:

方式一:使用 SET 賦值。

可以使用形如 set @變量名=變量值 或者 set@變量名:=變量值 的方式賦值。

SET @var_name = expr [, @var_name = expr] ...
或
SET @var_name := expr [, @var_name := expr] ...

image.png

方式二:使用 select 賦值。

select @變量名:=變量值
select @變量名:=字段名 from table where ... limit 1;

image.png

繼續舉個例子,表記錄如下:
image.png

image.png

image.png

注意: 通過查詢表給變量賦值時,需保證查詢結果只有一條記錄,如上result2的結果集這種查詢了2條。

另外再介紹本文實現中涉及的另外2個mysql函數,這裏就簡單介紹下:


if(express1,express2,express3)條件語句:

if語句類似三目運算符,當exprss1成立時,執行express2,否則執行express3;


FIND_IN_SET(str,strlist),str 要查詢的字符串,strlist 字段名 參數以”,”分隔 如 (1,2,3,6),查詢字段(strlist)中包含(str)的結果.


concat_ws()函數, 表示concat with separator,即有分隔符的字符串連接:

select concat_ws(',','11','22',NULL); 返回 11,22。

下面進入本文正題,查詢當前節點下的所有子節點:

select id
from (
        select t1.id,
            if(
                find_in_set(pid, @pids) > 0,
                @pids := CONCAT_WS(',',@pids, id),
                0
            ) as ischild
        from (
                select id,
                    pid
                from city t
                order by id
            ) t1,
            (
                select @pids := 11
            ) t2
    ) t3
where ischild != 0;

image.png

image.png

上面我們查詢節點id=11(武漢市)下的所有節點。上面語句看似複雜,其實不難理解,我們來分下該sql是怎麼實現結果集的。
我們先從最裏面的子查詢分析:
我們看到第二個from後面是跟了兩張表:t1和t2, t2是一個用戶變量,其結果集作爲t2,
image.png

,t1表很好理解就是city的所有記錄作爲表t1,我們再看t3表是什麼?
image.png

上面高亮部分即爲t3的結果集,其目的就是將當前要查詢的子節點id用逗號連接,

如果pid值在@pids中,則設置@pids用其用戶變量+id逗號連接組成新字段ischild。因爲@pids查詢到匹配記錄就重新賦值了,
所以大家不難理解其滿足條件下的子節點。
image.png
上面就是關於遞歸查詢的實現。當然還有另外一種查法:

SELECT t1.id 
FROM (SELECT id,pid FROM city WHERE pid IS NOT NULL) t1,
     (SELECT @pid := 11) t2
WHERE FIND_IN_SET(pid, @pid) > 0 
  AND @pid := concat(@pid, ',', id)
-- union select id from city where id = 11 order by id;

如果想查詢結果包含自身ID(如上面的id=11),加上後邊的union即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章