原文鏈接: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] ...
方式二:使用 select 賦值,
select @變數名:=變數值 select @變數名:=欄位名 from table where ... limit 1;
繼續舉個例子,表記錄如下:
注意: 通過查詢表給變數賦值時,需保證查詢結果只有一條記錄,如上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;
上面我們查詢節點id=11(武漢市)下的所有節點,上面陳述句看似復雜,其實不難理解,我們來分下該sql是怎么實作結果集的,
我們先從最里面的子查詢分析:
我們看到第二個from后面是跟了兩張表:t1和t2, t2是一個用戶變數,其結果集作為t2,
,t1表很好理解就是city的所有記錄作為表t1,我們再看t3表是什么?
上面高亮部分即為t3的結果集,其目的就是將當前要查詢的子節點id用逗號連接,
如果pid值在@pids中,則設定@pids用其用戶變數+id逗號連接組成新欄位ischild,因為@pids查詢到匹配記錄就重新賦值了,
所以大家不難理解其滿足條件下的子節點,
上面就是關于遞回查詢的實作,當然還有另外一種查法:
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即可,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/548258.html
標籤:MySQL
下一篇:P3 創建資料庫
