Mysql樹形表的2種查詢解決方案(遞歸與自連接)
你有沒有遇到過這樣一種情況:
一張表就實現(xiàn)了一對多的關(guān)系,并且表中每一行數(shù)據(jù)都存在“爺爺-父親-兒子-…”的聯(lián)系,這也就是所謂的樹形結(jié)構(gòu)
對于這樣的表很顯然想要通過查詢來實現(xiàn)價值絕對是不能只靠select * from table 來實現(xiàn)的,下面提供兩種解決方案:
1.自連接
inner join 關(guān)鍵可以實現(xiàn)多種分類的查詢,其實SQL很簡單
SELECT one.id one_id, one.label one_label, two.id two_id, two.label two_label FROM course_category one INNER JOIN course_category two ON two.parentid=one.id INNER JOIN course_category three ON three.parentid=two.id WHERE one.id='1' AND one.is_show='1' AND two.is_show='1' ORDER BY one.orderby,two.orderby
也是規(guī)規(guī)矩矩的就查出一整棵樹
這種查詢的原則就是通過parentId去實現(xiàn),“爺爺找爸爸,爸爸找兒子,兒子找孫子”,下面來逐幀慢放:
1.one
2.one,two
3.one,two,three
可以看到,只有在樹的層級確定的情況下我才能選擇性的去自連接子表,某種意義上來講這種方法存在弊端,我要是insert進(jìn)去層級更低的新子節(jié)點那我的sql就得改變,從而就造成了一個“動一發(fā)而牽全身”的硬編碼問題,實在是不夠穩(wěn)妥!
2.遞歸!
向上遞歸
首先聲明,如果mysql的版本低于8是不支持遞歸查詢的函數(shù)的!
下面來看一下如何用遞歸優(yōu)雅的實現(xiàn),從樹根查到樹頂:
先來看一個簡單的Demo
with RECURSIVE t1 AS( SELECT 1 AS n union all SELECT n+1 FROM t1 WHERE n<5 ) SELECT * from t1
該怎么理解這每一步呢?
WITH RECURSIVE t1 AS:
這是遞歸查詢的開始,創(chuàng)建了一個名為t1的遞歸表。
SELECT 1 AS n:
在t1表中,插入了一個初始行,值為1,命名為n。
UNION ALL:
使用UNION ALL運算符將初始行和遞歸查詢結(jié)果合并,形成遞歸步驟。這也就是下次遞歸的起點表
SELECT n+1 FROM t1 WHERE n<5:
遞歸部分的查詢,從t1表中選擇n加1的結(jié)果,當(dāng)n小于5時進(jìn)行遞歸。
SELECT * FROM t1:
最終查詢,返回t1表的所有行。
其實在使用遞歸的過程只需要注意要去避免死龜就好!
如何去查開頭的那張樹形表呢?這樣就好:
with recursive temp as ( select * from course_category p where id= '1' union all select t.* from course_category t inner join temp on temp.id = t.parentid ) select * from temp order by temp.id, temp.orderby
下面我們逐幀分析:
其實關(guān)鍵的地方就在于第三步,在樹根的基礎(chǔ)上去找葉子:
神之一手:select t.* from course_category t inner join temp on temp.id = t.parentid
這就是遞歸相較于第一種方式可以無視層級inner jion的關(guān)鍵,因為這個動作已經(jīng)被遞歸自動完成了,遞歸巧妙地一點就在這里!
向下遞歸
基于向上遞歸父找子的思想,向下遞歸則是子找父,即在葉子基礎(chǔ)上union all之后去找根
子的parentId=父的id
with recursive temp as ( select * from course_category p where id= '1-1-1' union all select t.* from course_category t inner join temp on temp.parentid = t.id //temp表是下次遞歸的基礎(chǔ) ) select * from temp order by temp.id, temp.orderby
值得注意的是Mysql為了避免無限遞歸遞歸次數(shù)為1000次,也可以人為來設(shè)置cte_max_recursion_depth和max_execution_time來自定義遞歸深度和執(zhí)行時間
使用遞歸的好處無需言語,一次io連接就搞定了全部
總結(jié)
到此這篇關(guān)于Mysql樹形表的2種查詢解決方案的文章就介紹到這了,更多相關(guān)Mysql樹形表查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解MySQL執(zhí)行原理、邏輯分層、更改數(shù)據(jù)庫處理引擎
在本文里我們給大家總結(jié)了關(guān)于MySQL執(zhí)行原理、邏輯分層、更改數(shù)據(jù)庫處理引擎的相關(guān)知識點,需要的讀者們一起學(xué)習(xí)下。2019-02-02幾種MySQL中的聯(lián)接查詢操作方法總結(jié)
這篇文章主要介紹了幾種MySQL中的聯(lián)接查詢操作方法總結(jié),文中包括一些代碼舉例講解,需要的朋友可以參考下2015-04-04