SQLServer CTE遞歸和循環對比的優勢--典型案例

首先,我們新建一張測試用的臨時表#country,其中包含三個字段,AreaNam(地名) ,BelongTo(上級地名) ,Msg(地方簡介)
Create table #country (AreaNam NVARCHAR(10),BelongTo Nvarchar(10),Msg varchar(100))

下面我們往這張表裏插入一堆測試數據:

INSERT INTO #country
SELECT '中國','中國',null union all
SELECT '江蘇','中國',null union all
SELECT '南京','江蘇',null union all
SELECT '無錫','江蘇',null union all
SELECT '徐州','江蘇',null union all
SELECT '揚州','江蘇',null union all
SELECT '蘇州','江蘇',null union all
SELECT '六合區','南京',null union all
SELECT '江寧區','南京',null union all
SELECT '浦口區','南京',null union all
SELECT '仙林區','南京',null union all
SELECT '建鄴區','南京',null union all
SELECT '寶應','揚州',null union all
SELECT '儀徵','揚州',null union all
SELECT '小官莊','寶應',null union all
SELECT '範水','寶應',null union all
SELECT '魯垛','寶應',null union all
SELECT '安宜','寶應',null union all
SELECT '組全','小官莊',null union all
SELECT '房橋','小官莊',null union all
SELECT '直下溝','小官莊',null union all
SELECT '山東','中國',null union all
SELECT '濟南','山東',null union all
SELECT '青島','山東',null union all
SELECT '淄博','山東',null union all
SELECT '煙臺','山東',null union all
SELECT '張店','淄博',null union all
SELECT '博山','淄博',null union all
SELECT '淄川','淄博',null union all
SELECT '龍王山','浦口區',null union all
SELECT '高新區','浦口區',null union all
SELECT '陸軍指揮學院','浦口區',null union all
SELECT '南京信息工程大學','浦口區',null union all
SELECT '金陵學院','浦口區',null

到這裏,表結構已經完成了,這張表的表結構應該不難理解。

但是下面問題來了,有要求查找出南京包含南京以內(屬於南京)的所有地名,因爲如果數據量比較大的話,我們根本無法確定一個城市往下分了多少級地名,如果分的層級太多的話,使用循環取實現查詢結果也是一個可行的方案,sql如下:

DECLARE @CITY NVARCHAR(MAX)='南京'
Create table #TEMP (AreaNam NVARCHAR(10),BelongTo Nvarchar(10),Msg varchar(100))
Create table #tempAreaname (AreaNam NVARCHAR(10))
Create table #tempAreanametemp (AreaNam NVARCHAR(10))
INSERT INTO #tempAreaname 
SELECT @CITY
INSERT INTO #TEMP
SELECT * FROM #country WHERE AreaNam=@CITY
WHILE 1=1
BEGIN
	insert into #tempAreanametemp
	SELECT areanam  FROM #country WHERE belongto IN(select areanam from #tempAreaname)

	IF @@ROWCOUNT<>0
	BEGIN 
		INSERT INTO #TEMP
		SELECT * FROM #country WHERE belongto IN(select areanam from #tempAreaname)
		delete from #tempAreaname
		insert into #tempAreaname
		select * from #tempAreanametemp
		delete from #tempAreanametemp		
	END
	ELSE
	BEGIN	
		SELECT * FROM #TEMP
		DROP TABLE #TEMP
		DROP TABLE #tempAreaname
		DROP TABLE #tempAreanametemp
		RETURN
	END
END
查詢結果如下:

AreaNam BelongTo Msg
南京 江蘇 NULL
六合區 南京 NULL
江寧區 南京 NULL
浦口區 南京 NULL
仙林區 南京 NULL
建鄴區 南京 NULL
龍王山 浦口區 NULL
高新區 浦口區 NULL
陸軍指揮學院 浦口區 NULL
南京信息工程大學 浦口區 NULL
金陵學院 浦口區 NULL


這正是我們所想要的結果,但是總感覺這寫法太複雜而且執行效率也不是很高,當然啦用循環去寫的話肯定也有簡單一點的寫法的,這不是我們今天的重點。今天的重點是用CTE遞歸的方式去實現我們所想要的結果,SQL如下:

WITH CTE AS (
SELECT AreaNam,BelongTo,Msg FROM #country WHERE AreaNam='南京'
UNION ALL
SELECT  A.AreaNam,A.BelongTo,A.Msg FROM #country A INNER JOIN CTE B ON A.BelongTo=B.AreaNam
)
SELECT * FROM CTE

查詢結果也是一樣一樣的:
AreaNam BelongTo Msg
南京 江蘇 NULL
六合區 南京 NULL
江寧區 南京 NULL
浦口區 南京 NULL
仙林區 南京 NULL
建鄴區 南京 NULL
龍王山 浦口區 NULL
高新區 浦口區 NULL
陸軍指揮學院 浦口區 NULL
南京信息工程大學 浦口區 NULL
金陵學院 浦口區 NULL
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章