今天用到了sql的遞歸查詢。遞歸查詢是CTE語句with xx as(....)實現的。html
假如表Category數據以下。sql
咱們想查找機槍這個子分類極其層次關係(經過子節點,查詢全部層級節點)。如下是查詢語句spa
WITH tt AS ( SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=15 --定位點成員 UNION ALL SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN tt ON tt.Parent=c.CategoryId --遞歸成員 ) SELECT * FROM tt
執行結果3d
CTE遞歸說明:htm
上面的腳本,我註明了定位點成員,和遞歸成員。blog
定位點成員造成了查詢的基本結果集。其實就是你用於查詢的"引子"數據。在遞歸cte開始執行時,第一次執行,會先執行定位成員,並獲得寄出結果集。遞歸
遞歸成員是每次遞歸執行的語句。我的意淫,每次遞歸時,是把上一次遞歸查詢得出的結果集傳遞給遞歸語句,並繼續執行遞歸it
在遞歸時,若是上一次查詢沒有返回結果集,則終止遞歸。(這點讓我糾結好久,由於沒有顯示的著名什麼時候結束遞歸~)io
意淫的執行步驟--------------------class
首先執行定位成員:
SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=46
並獲得告終果集:
而後執行第一次遞歸:
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN tt ON tt.Parent=c.CategoryId
執行遞歸時,join了 cte 語句自己,就是tt,join裏的語句跟with as裏的語句同樣。其實語句能夠意淫成醬紫
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN ( --SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=15 華麗的忽略掉了 --UNION ALL 華麗的忽略掉了 SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN tt ON tt.Parent=c.CategoryId --咱們繼續遞歸~ )tt ON tt.Parent=c.CategoryId
此次遞歸能夠拆分紅兩個操做,查詢結果和繼續遞歸。
1.由於是第一次遞歸,因此將執行定位成員得出的結果集帶入,進行查詢。其實執行的是醬紫
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN ( SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=46 )tt ON tt.Parent=c.CategoryId
發現有結果:
則繼續進行遞歸:
遞歸時語句仍是醬紫:
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN ( --SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=15 華麗的忽略掉了 --UNION ALL 華麗的忽略掉了 SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN tt ON tt.Parent=c.CategoryId --咱們繼續遞歸 )tt ON tt.Parent=c.CategoryId
此次遞歸查詢,所用的結果集是上次遞歸查詢得出的(再也不是定位成員的結果集了)。就是用的下面這個結果集
執行語句是醬紫的
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN ( SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN ( SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=46 )tt ON tt.Parent=c.CategoryId )tt ON tt.Parent=c.CategoryId
第一層join的數據是上次遞歸查詢的語句。
發現有結果:
ok繼續遞歸吧
繼續上面的步驟,帶入上次查詢的結果集進行查詢。
執行語句實際上是醬紫:
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN ( SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN ( SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN ( SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=46 )tt ON tt.Parent=c.CategoryId )tt ON tt.Parent=c.CategoryId )tt ON tt.Parent=c.CategoryId
得出的結果集:
啥也木有,終止遞歸。
而後用union all 把每次遞歸的結果集合起來。得出了最終的查詢結果。
這個步驟是意淫的,我還設想了其餘的方式。但在終止遞歸上都存在問題,因此最終把文章寫成醬紫。
參考文章:https://www.cnblogs.com/youngmin/p/6256478.html