SQL種獲取單表篩選數據的子級或者父級,或者子父級存儲過程--通用

詳見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
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章