SQL 遞歸查詢,意淫CTE遞歸的執行步驟

 

今天用到了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

相關文章
相關標籤/搜索