詳解SQL中的遞歸問題
遞歸查詢原理
SQL Server中的遞歸查詢是通過CTE(表表達式)來實現(xiàn)。至少包含兩個查詢,第一個查詢?yōu)槎c成員,定點成員只是一個返回有效表的查詢,用于遞歸的基礎(chǔ)或定位點;第二個查詢被稱為遞歸成員,使該查詢稱為遞歸成員的是對CTE名稱的遞歸引用是觸發(fā)。在邏輯上可以將CTE名稱的內(nèi)部應(yīng)用理解為前一個查詢的結(jié)果集。
遞歸查詢的終止條件
遞歸查詢沒有顯式的遞歸終止條件,只有當?shù)诙€遞歸查詢返回空結(jié)果集或是超出了遞歸次數(shù)的最大限制時才停止遞歸。是指遞歸次數(shù)上限的方法是使用MAXRECURION。
遞歸查詢的優(yōu)點
效率高,大量數(shù)據(jù)集下,速度比程序的查詢快。
遞歸的常見形式
- WITH CTE AS (
- SELECT column1,column2... FROM tablename WHERE conditions
- UNION ALL
- SELECT column1,column2... FROM tablename
- INNER JOIN CTE ON conditions
- )
遞歸查詢示例
創(chuàng)建測試數(shù)據(jù),有一個員工表Employee,ManagerID是UserID的父節(jié)點,這是一個非常簡單的層次結(jié)構(gòu)模型。
- USE SQL_Road
- GO
- CREATE TABLE Employee
- (
- UserID INT,
- ManagerID INT,
- Name NVARCHAR(10)
- )
- INSERT INTO dbo.Employee
- SELECT 1,-1,N'Boss'
- UNION ALL
- SELECT 11,1,N'A1'
- UNION ALL
- SELECT 12,1,N'A2'
- UNION ALL
- SELECT 13,1,N'A3'
- UNION ALL
- SELECT 111,11,N'B1'
- UNION ALL
- SELECT 112,11,N'B2'
- UNION ALL
- SELECT 121,12,N'C1'
查詢一下Employee表里的數(shù)據(jù)
查詢每個User的的直接上級Manager
- WITH CTE AS(
- SELECT UserID,ManagerID,Name,Name AS ManagerName
- FROM dbo.Employee
- WHERE ManagerID=-1
- UNION ALL
- SELECT c.UserID,c.ManagerID,c.Name,p.Name AS ManagerName
- FROM CTE P
- INNER JOIN dbo.Employee c ON p.UserID=c.ManagerID
- )
- SELECT UserID,ManagerID,Name,ManagerName
- FROM CTE
結(jié)果如下:
我們來解讀一下上面的代碼
1、查詢ManagerID=-1,作為根節(jié)點,這是遞歸查詢的起始點。
2、迭代公式是 UNION ALL 下面的查詢語句。在查詢語句中調(diào)用中CTE,而查詢語句就是CTE的組成部分,即 “自己調(diào)用自己”,這就是遞歸的真諦所在。
所謂迭代,是指每一次遞歸都要調(diào)用上一次查詢的結(jié)果集,UNION ALL是指每次都把結(jié)果集并在一起。
3、迭代公式利用上一次查詢返回的結(jié)果集執(zhí)行特定的查詢,直到CTE返回NULL或達到最大的迭代次數(shù),默認值是32。最終的結(jié)果集是迭代公式返回的各個結(jié)果集的并集,求并集是由UNION ALL 子句定義的,并且只能使用UNION ALL
查詢路徑
下面我們通過層次結(jié)構(gòu)查詢子節(jié)點到父節(jié)點的PATH,我們對上面的代碼稍作修改:
- WITH CTE AS(
- SELECT UserID,ManagerID,Name,CAST(Name AS NVARCHAR(MAX)) AS LPath
- FROM dbo.Employee
- WHERE ManagerID=-1
- UNION ALL
- SELECT c.UserID,c.ManagerID,c.Name,p.LPath+'->'+c.Name AS LPath
- FROM CTE P
- INNER JOIN dbo.Employee c ON p.UserID=c.ManagerID
- )
- SELECT UserID,ManagerID,Name,LPath
- FROM CTE
其中CAST(Name AS NVARCHAR(MAX))是將Name的長度設(shè)置為最大,防止字段過長超出字段長度。具體結(jié)果如下:
以上就是遞歸查詢的一些知識介紹了,自己可以動手實驗一下,這個一般在面試中也經(jīng)常會考察面試者,希望能幫助到大家~