SQL SERVER遞歸查詢的實(shí)現(xiàn)
有示例數(shù)據(jù),表名為SYS_Department
id | departmentName | parentId | remark | isEnable | staffId |
2 | 總經(jīng)理 | 1 | 總經(jīng)理 | 1 | |
3 | 賬務(wù)部 | 2 | 賬務(wù)部 | 1 | 1006 |
4 | 技術(shù)部 | 2 | 技術(shù)部 | 1 | 1004 |
9 | 產(chǎn)品部 | 2 | 產(chǎn)品部 | 1 | 1005 |
10 | 市場(chǎng)部 | 2 | 市場(chǎng)部 | 1 | |
11 | 人事部 | 2 | 人事部 | 1 | 1013 |
5 | 測(cè)試部 | 4 | 測(cè)試部 | 1 | 1002 |
6 | 開(kāi)發(fā)部 | 4 | 開(kāi)發(fā)部 | 1 | 1003 |
7 | 設(shè)計(jì)部 | 4 | 設(shè)計(jì)部 | 1 | |
8 | 物聯(lián)部 | 4 | 物聯(lián)部 | 1 | |
12 | JAVA一部 | 6 | JAVA一部 | 1 | 1009 |
13 | JAVA二部 | 6 | JAVA二部 | 1 | |
14 | .NET部 | 6 | .NET部 | 1 | 1008 |
15 | 前端部 | 6 | 前端部 | 1 |
遞歸查詢?cè)?/p>
SQL Server中的遞歸查詢是通過(guò)CTE(表表達(dá)式)來(lái)實(shí)現(xiàn)。至少包含兩個(gè)查詢,第一個(gè)查詢?yōu)槎c(diǎn)成員,定點(diǎn)成員只是一個(gè)返回有效表的查詢,用于遞歸的基礎(chǔ)或定位點(diǎn);第二個(gè)查詢被稱為遞歸成員,使該查詢稱為遞歸成員的是對(duì)CTE名稱的遞歸引用是觸發(fā)。在邏輯上可以將CTE名稱的內(nèi)部應(yīng)用理解為前一個(gè)查詢的結(jié)果集。
遞歸查詢語(yǔ)法
with 子查詢名稱 查詢字段列表 as --查詢字段列表輸入格式為([查詢字段名1],[查詢字段名2],...),也可用*代替,需要注意的是此處的查詢字段列表中的字段與下方內(nèi)容中定點(diǎn)成員與遞歸成員查詢字段列表內(nèi)容需一致 ( --定點(diǎn)成員 select 查詢字段列表 from 查詢表名 where 查詢條件 union all --遞歸成員 select 查詢字段列表 from 查詢表名 a inner join 子查詢名稱 on 遞歸條件 ) select 顯示字段名 from 子查詢名稱
已示例數(shù)據(jù)為例
--查詢1 --通過(guò)根節(jié)點(diǎn)向下查找該根節(jié)點(diǎn)下的子節(jié)點(diǎn) with temp([id],[departmentName],[parentId]) as --temp([id],[departmentName])指定temp結(jié)果集中的列,如設(shè)置需包含聯(lián)表?xiàng)l件 ( select [id],[departmentName],[parentId] from SYS_Department where id = 2 union all select a.[id],a.[departmentName],a.[parentId] from SYS_Department a inner join temp on a.[parentId] = temp.[id] ) select [id],[departmentName] from temp --查詢2 --通過(guò)子節(jié)點(diǎn)向上查找該子節(jié)點(diǎn)的根節(jié)點(diǎn) with temp([id],[departmentName],[parentId]) as ( select [id],[departmentName],[parentId] from SYS_Department where id = 2 union all select a.[id],a.[departmentName],a.[parentId] from SYS_Department a inner join temp on --調(diào)換查詢字段 a.[id] = temp.[parentId] ) select [id],[departmentName] from temp
查詢2查詢結(jié)果
mysql示例 使用recursive關(guān)鍵字
--Mysql 查詢時(shí)聯(lián)表?xiàng)l件與SQL SERVER相反 --父查子 with recursive temp(Id,DepartmentName,ParentId) as (select Id,DepartmentName,ParentId from SYS_Department where id = 2 union all select a.Id,a.DepartmentName,a.ParentId from SYS_Department a inner join temp on a.ParentId = temp.Id) select * from temp --子查父 with recursive temp(Id,DepartmentName,ParentId) as (select Id,DepartmentName,ParentId from SYS_Department where id = 2 union all select a.Id,a.DepartmentName,a.ParentId from SYS_Department a inner join temp on a.Id = temp.ParentId ) select * from temp
不指定查詢字段列表
--查詢1 --不指定子查詢查詢字段列表 with temp as ( --查詢表中所有字段 select * from SYS_Department where id = 2 union all --查詢主表中所有字段(根據(jù)UNION ALL語(yǔ)法需與定點(diǎn)成員查詢字段保持一致) select a.* from SYS_Department a inner join temp on a.[parentId] = temp.[id] ) --顯示表中所有字段 select * from temp --查詢2 --不指定子查詢查詢字段列表 with temp as ( --查詢表中所有字段 select * from SYS_Department where id = 2 union all --查詢主表中所有字段(根據(jù)UNION ALL語(yǔ)法需與定點(diǎn)成員查詢字段保持一致) select a.* from SYS_Department a inner join temp on a.[parentId] = temp.[id] ) --顯示表中id字段 select id from temp
查詢結(jié)果1
查詢結(jié)果2
總結(jié):
以樹(shù)的概念去理解查詢?cè)砜赡芟鄬?duì)比較容易一些,以下是以結(jié)果反推的個(gè)人理解:
關(guān)鍵字:
定點(diǎn)成員(示例語(yǔ)句中:select * from SYS_Department where id = 2)
遞歸成員(示例語(yǔ)句中:select a.* from SYS_Department a inner join temp on a.[parentId] = temp.[id])
拼接(使用UNION ALL)
SQL遞歸查詢是以定點(diǎn)成員為查詢起始點(diǎn)(即語(yǔ)句中的select * from SYS_Department where id = 2),第一次查詢時(shí)取到定點(diǎn)成員的子節(jié)點(diǎn)(即示例數(shù)據(jù)中parentid=2的數(shù)據(jù),可以將查詢起始點(diǎn)理解為樹(shù)的根節(jié)點(diǎn)),通過(guò)特定的順序遍歷取到的子節(jié)點(diǎn)(遍歷順序經(jīng)測(cè)試為倒序遍歷,即先遍歷id=4的數(shù)據(jù),再遍歷id=3的數(shù)據(jù)),當(dāng)該子節(jié)點(diǎn)下存在數(shù)據(jù)時(shí)(即已select a.* from SYS_Department a inner join temp on a.[parentId] = temp.[id]的查詢結(jié)果不為NULL時(shí))顯示數(shù)據(jù)并繼續(xù)遍歷該節(jié)點(diǎn),直至查詢導(dǎo)的結(jié)果為空或達(dá)到最大的迭代次數(shù)(默認(rèn)為100),最終將所有節(jié)點(diǎn)遍歷完成并將遍歷的結(jié)果以UNION ALL語(yǔ)句拼接輸出結(jié)果集。
以示例數(shù)據(jù)為例,反推的查詢流程以及數(shù)據(jù)如圖所示:
1.第一次遞歸時(shí)(目前無(wú)法確定開(kāi)始執(zhí)行的順序是先執(zhí)行定點(diǎn)成員語(yǔ)句后遞歸還是獲取到子節(jié)點(diǎn)后遞歸,猜測(cè)順序?yàn)閳?zhí)行完定點(diǎn)成員SQL后進(jìn)行第一次遞歸)獲取拼接下圖中
2.遞歸遍歷通過(guò)定點(diǎn)成員獲取到的子節(jié)點(diǎn),先遍歷id=11的節(jié)點(diǎn),但該節(jié)點(diǎn)下獲取的數(shù)據(jù)為空所以不拼接任何數(shù)據(jù),id=10和9的同理,當(dāng)遍歷到id為4的節(jié)點(diǎn)時(shí),獲取拼接下圖數(shù)據(jù)
3.遞歸遍歷上圖中獲取到的節(jié)點(diǎn),先遍歷id=8的節(jié)點(diǎn),但該節(jié)點(diǎn)下獲取的數(shù)據(jù)為空所以不拼接任何數(shù)據(jù),id=7和5的同理,當(dāng)遍歷到id為6的節(jié)點(diǎn)時(shí),獲取拼接下圖數(shù)據(jù)
4.遞歸遍歷上圖中獲取到的節(jié)點(diǎn),先遍歷id=15的節(jié)點(diǎn),但該節(jié)點(diǎn)下獲取的數(shù)據(jù)為空所以不拼接任何數(shù)據(jù),id=14,13,12的節(jié)點(diǎn)同理
5.此時(shí)以id=4的節(jié)點(diǎn)為根節(jié)點(diǎn)的所有節(jié)點(diǎn)已遍歷完成,繼續(xù)遞歸遍歷通過(guò)定點(diǎn)成員獲取到的子節(jié)點(diǎn),即遍歷id=3的節(jié)點(diǎn),但該節(jié)點(diǎn)下獲取的數(shù)據(jù)為空所以不拼接任何數(shù)據(jù),最終顯示結(jié)果集如下圖所示
原文參考:
WITH common_table_expression (Transact-SQL) | Microsoft Docs
Recursive Queries Using Common Table Expressions | Microsoft Docs
思路借鑒:SQL中的遞歸的用法_SQL數(shù)據(jù)庫(kù)開(kāi)發(fā)的博客-CSDN博客
到此這篇關(guān)于SQL SERVER遞歸查詢的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)SQL 遞歸查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MySQL遞歸查詢樹(shù)狀表的子節(jié)點(diǎn)、父節(jié)點(diǎn)具體實(shí)現(xiàn)
- 有關(guān)數(shù)據(jù)庫(kù)SQL遞歸查詢?cè)诓煌瑪?shù)據(jù)庫(kù)中的實(shí)現(xiàn)方法
- SQL Server 樹(shù)形表非循環(huán)遞歸查詢的實(shí)例詳解
- sql server實(shí)現(xiàn)遞歸查詢的方法示例
- sqlserver實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)遞歸查詢(無(wú)限極分類)的方法
- Mysql樹(shù)形遞歸查詢的實(shí)現(xiàn)方法
- PostgreSQL樹(shù)形結(jié)構(gòu)的遞歸查詢示例
- MySQL遞歸查詢的3種實(shí)現(xiàn)方式實(shí)例
- mysql實(shí)現(xiàn)遞歸查詢的方法示例
- mysql遞歸查詢所有子集的實(shí)現(xiàn)方法
相關(guān)文章
mysql 復(fù)制原理與實(shí)踐應(yīng)用詳解
這篇文章主要介紹了mysql 復(fù)制原理與實(shí)踐應(yīng)用,結(jié)合實(shí)例形式詳細(xì)分析了MySQL數(shù)據(jù)庫(kù)復(fù)制功能的原理、操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-02-02MySQL數(shù)據(jù)庫(kù)使用規(guī)范總結(jié)
本篇文章給大家詳細(xì)分類總結(jié)了數(shù)據(jù)庫(kù)相關(guān)規(guī)范,幫助大家發(fā)揮出數(shù)據(jù)庫(kù)的性能,感興趣的朋友可以了解下2020-08-08淺析MySQL數(shù)據(jù)的導(dǎo)出與導(dǎo)入知識(shí)點(diǎn)
在本文里我們給大家分享了關(guān)于MySQL數(shù)據(jù)的導(dǎo)出與導(dǎo)入的相關(guān)實(shí)例和知識(shí)點(diǎn)內(nèi)容,需要的朋友們跟著學(xué)習(xí)下。2019-03-03mysql server is running with the --skip-grant-tables option
今天在mysql中新建數(shù)據(jù)庫(kù)提示The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement,原來(lái)是數(shù)據(jù)中配置的--skip-grant-tables,這樣安全就降低了,這個(gè)一般當(dāng)忘記root密碼的時(shí)候需要這樣操作2017-07-07PHP5 mysqli的prepare準(zhǔn)備語(yǔ)句使用說(shuō)明
mysqli對(duì)prepare的支持對(duì)于大訪問(wèn)量的網(wǎng)站是很有好處的,它極大地降低了系統(tǒng)開(kāi)銷,而且保證了創(chuàng)建查詢的穩(wěn)定性和安全性.prepare準(zhǔn)備語(yǔ)句分為綁定參數(shù)和綁定結(jié)果2012-12-12mysql中sum float類型使用小數(shù)點(diǎn)的方法
使用sum示和時(shí)如果是float類型的數(shù)據(jù)就會(huì)出現(xiàn)小數(shù)點(diǎn)了,那么要如何解決這個(gè)問(wèn)題,下面介紹二種方法2013-11-11Windows系統(tǒng)中完全卸載MySQL數(shù)據(jù)庫(kù)實(shí)現(xiàn)重裝mysql
這篇文章主要介紹了Windows系統(tǒng)中完全卸載MySQL數(shù)據(jù)庫(kù)實(shí)現(xiàn)重裝mysql數(shù)據(jù)庫(kù)的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05