詳見SQL遞歸
---------------------------------------獲取所有子級
/*----------------------------------------------------------*/
/* [PC1recursion] */
/*----------------------------------------------------------*/
IF EXISTS ( SELECT 1 FROM sys.objects o WHERE object_id = object_id( N'[PC1recursion]' ) AND OBJECTPROPERTY( object_id, N'IsProcedure') = 1 )
DROP PROCEDURE [PC1recursion]
GO
CREATE PROC [PC1recursion]
(
@tbname VARCHAR(36) = '', --表明
@id varchar(50)='',--id名稱
@idValue varchar(36)='',--id值
@pid varchar(1000) = ''--父級ID名稱
)
AS
/*
功能:根據表,查詢該表嚇所有本級以及所有子級數據
參數:
返回:遞歸返回所有數據
編寫:ljr 2017-07-8
測試:
*/
BEGIN
declare @sql varchar(max)
set @sql='WITH cteTree
AS (SELECT *
FROM '+@tbname+'
WHERE '+@id+'='''+@idValue+''' --第一個查詢作爲遞歸的基點(錨點)
UNION ALL
SELECT '+@tbname+'.* --第二個查詢作爲遞歸成員, 下屬成員的結果爲空時,此遞歸結束。
FROM
cteTree INNER JOIN '+@tbname+' ON cteTree.'+@id+' ='+@tbname+'.'+@pid+')
select * into #all from cteTree
select distinct ScreenConfigID,ScreenTemplateID,ScreenType,PScreenConfigID,GroupName
into #main
from #all
select m.ScreenConfigID,m.ScreenTemplateID,m.ScreenType,m.PScreenConfigID,m.GroupName,
c.*
from #main m
left join #all c on m.ScreenConfigID=c.ScreenConfigID
drop table #main
drop table #all
'
print @sql
exec (@sql)
END
GO
列子:exec PC1recursion @tbname ='SY1Org', - 表明
@id ='orgID', - id名稱
@idValue ='40730451-F1D4-4A9D-8B57-E3858CA5CA23', - id值
@pid ='POrgID'
結果集:
樹形結果集展示:
-------------------------------------------------- - 獲取所有父級,子級或者所有
前面寫了一個通用的獲取子級的,最近項目又遇到獲取所有父級的,剛好這幾天不是那麼忙,於是就把2個整理了一下,寫到一個過程裏面來了,根據傳入參數等獲取子級父級等。暫不支持多表關聯查詢,只支持單表的拉取。
/*----------------------------------------------------------*/
/* [GetTbChildOrParentList] */
/*----------------------------------------------------------*/
IF EXISTS ( SELECT 1 FROM sys.objects o WHERE object_id = object_id( N'[GetTbChildOrParentList]' ) AND OBJECTPROPERTY( object_id, N'IsProcedure') = 1 )
DROP PROCEDURE [GetTbChildOrParentList]
GO
CREATE PROC [dbo].[GetTbChildOrParentList]
(
@tbname VARCHAR(100) = '', --表名
@id varchar(100)='',--id名稱
@colomn NVARCHAR(1000)='*',--查詢的字段
@sqlWhere varchar(1000)='',--篩選的條件
@type int = 0,--拉取篩選條件的子級還是父級;0 子級 1父級 2所有
@order varchar(100) ='', --排序字段,爲空則按照主鍵排序
@orderType int =0 ,--0 升序, 1降序
@pid varchar(100) = ''--父級ID名稱
)
AS
/*
功能:根據查詢條件查詢表中數據,以及篩選的數據的所有父級
參數:
返回:遞歸返回所有數據
編寫:ljr 2018-10-24
測試:
*/
BEGIN
declare @sql varchar(max)
--先拉取表中所有數據以及篩選的數據set @sql='
SET NOCOUNT ON
SELECT * INTO #ALL FROM '+@tbname+'
CREATE INDEX IX_ALL ON #ALL('+@id+') --給表#ALL建索引
SELECT * INTO #DATA FROM #ALL WHERE 1=1 AND '+@sqlWhere+'
CREATE INDEX IX_DATA ON #DATA('+@id+') --給表#DATA建索引
SELECT * INTO #P FROM #DATA WHERE 1=2--給父級表拷貝表結構
CREATE INDEX IX_P ON #P('+@id+') --給表#P建索引
SELECT * INTO #C FROM #DATA WHERE 1=2 --給子級表拷貝表結構
CREATE INDEX IX_C ON #C('+@id+') --給表#C建索引'
--然後在遞歸拉取父級或者子級
set @sql+='
IF '+CAST(@type AS NVARCHAR(2))+' = 1 OR '+CAST(@type AS NVARCHAR(2))+' = 2 -- 1父級,2所有
BEGIN
--遞歸拉取父級
;WITH CTEP AS (
SELECT * from #DATA
UNION ALL
SELECT D.* from CTEP
INNER JOIN #ALL D on CTEP.'+@pid+'=D.'+@id+'
)
INSERT #P
SELECT DISTINCT * FROM CTEP ;
END
IF '+CAST(@type AS NVARCHAR(2))+' = 0 OR '+CAST(@type AS NVARCHAR(2))+' = 2 --0 子級,,2所有
BEGIN
--遞歸拉取子級
;WITH CTEC AS (
SELECT * from #DATA
UNION ALL
SELECT D.* from CTEC
INNER JOIN #ALL D on CTEC.'+@id+'=D.'+@pid+'
)
INSERT #C
SELECT DISTINCT * FROM CTEC ;
END
IF '+CAST(@type AS NVARCHAR(2))+' = 0 --0 子級
BEGIN
SELECT '+@colomn+' FROM #C ORDER BY '+ CASE WHEN ISNULL(@order,'')=''THEN @id ELSE @order END +' '+ CASE WHEN @orderType=0 THEN '' ELSE 'DESC' END +'
END
ELSE IF '+CAST(@type AS NVARCHAR(2))+' = 1 -- 1父級
BEGIN
SELECT '+@colomn+' FROM #P ORDER BY '+ CASE WHEN ISNULL(@order,'')=''THEN @id ELSE @order END +' '+ CASE WHEN @orderType=0 THEN '' ELSE 'DESC' END +'
END
ELSE IF '+CAST(@type AS NVARCHAR(2))+' = 2 -- 2所有
BEGIN
SELECT *
FROM (
SELECT '+@colomn+' FROM #C
UNION
SELECT '+@colomn+' FROM #P
) A ORDER BY '+ CASE WHEN ISNULL(@order,'')=''THEN @id ELSE @order END +' '+ CASE WHEN @orderType=0 THEN '' ELSE 'DESC' END +'
END
--清除臨時表
DROP TABLE #ALL
DROP TABLE #DATA
DROP TABLE #P
DROP TABLE #C
SET NOCOUNT OFF '
PRINT @sql
EXEC (@sql)
END
GO