获取父子层次结构中的所有父项

时间:2014-04-01 20:22:43

标签: sql sql-server sql-server-2008 common-table-expression

我的表格中有以下数据

ID          NAME                           PARENTID    STATUS
----------- ------------------------------ ----------- ------
1           Folder A                       0           0
2           Folder B                       1           0
3           Folder C                       2           1
4           Folder D                       1           0
5           Folder E                       4           0
6           Folder G                       5           0
7           Folder H                       6           1

以上记录来自表格[@Temp]。

[Name] - Folder Name
[ID] - Unique ID of folder in database (identity)
[ParentID] - Represents the parent of current folder.

查询以填充表格中的上述数据:

  DECLARE @Temp TABLE
    (
      [ID] INT IDENTITY(1, 1) ,
      [NAME] VARCHAR(30) ,
      [PARENTID] INT,
      [STATUS] BIT
    )

  INSERT    INTO @Temp
            SELECT  'Folder A' ,
                    0, 0
            UNION
            SELECT  'Folder B' ,
                    1, 0
            UNION
            SELECT  'Folder C' ,
                    2, 1
            UNION
            SELECT  'Folder D' ,
                    1, 0
            UNION
            SELECT  'Folder E' ,
                    4, 0
            UNION
            SELECT  'Folder G' ,
                    5, 0
            UNION
            SELECT  'Folder H' ,
                    6, 1              

我有以下查询来获取status = 1

的记录
  SELECT    *
  FROM      @Temp WHERE [STATUS]=1      

,它提供以下输出

ID          NAME                           PARENTID    STATUS
----------- ------------------------------ ----------- ------
3           Folder C                       2           1
7           Folder H                       6           1

我的目标是获取那些记录,这些记录是上述查询附带的记录的父项(直到parentid = 0)。即我想获得包含文件夹C和文件夹H的父项的输出:

ID          NAME                           PARENTID    STATUS
----------- ------------------------------ ----------- ------
1           Folder A                       0           0
2           Folder B                       1           0
3           Folder C                       2           1
4           Folder D                       1           0
5           Folder E                       4           0
6           Folder G                       5           0
7           Folder H                       6           1

2 个答案:

答案 0 :(得分:0)

  DECLARE @Temp TABLE
    (
      [ID] INT IDENTITY(1, 1) ,
      [NAME] VARCHAR(30) ,
      [PARENTID] INT ,
      [STATUS] BIT
    )

  INSERT    INTO @Temp
            SELECT  'Folder A' ,
                    0 ,
                    0
            UNION
            SELECT  'Folder B' ,
                    1 ,
                    0
            UNION
            SELECT  'Folder C' ,
                    2 ,
                    1
            UNION
            SELECT  'Folder D' ,
                    1 ,
                    0
            UNION
            SELECT  'Folder E' ,
                    4 ,
                    0
            UNION
            SELECT  'Folder G' ,
                    5 ,
                    1
            UNION
            SELECT  'Folder H' ,
                    6 ,
                    0                    


  CREATE  TABLE #TempTable
    (
      [RowIndex] INT IDENTITY(1, 1) ,
      [ID] INT ,
      [ParentID] INT
    )
  DECLARE @TempIds TABLE ( [ID] INT )               
  INSERT    INTO #TempTable
            ( [ID] ,
              [ParentID]
            )
            SELECT  [ID] ,
                    [ParentID]
            FROM    @Temp
            WHERE   [STATUS] = 1  



  DECLARE @intFlag INT
  DECLARE @Count INT
  SET @intFlag = 1
  SELECT    @Count = COUNT(1)
  FROM      @Temp
  WHILE ( @intFlag <= @Count )
    BEGIN
        PRINT @intFlag

        DECLARE @ID INT
        SELECT  @ID = [ParentID]
        FROM    #TempTable
        WHERE   RowIndex = @intFlag
        SET @intFlag = @intFlag + 1;
        WITH    CTE
                  AS ( SELECT   ID ,
                                ParentID
                       FROM     @Temp
                       WHERE    ID = @ID
                       UNION ALL
                       SELECT   MainTbl.ID ,
                                MainTbl.ParentID
                       FROM     @Temp MainTbl
                                INNER JOIN cte ON MainTbl.ID = cte.ParentID
                     )
            INSERT  INTO @TempIds
                    SELECT  ID
                    FROM    CTE  


    END



  ;WITH  cte
          AS ( SELECT    DISTINCT
                        ID
               FROM     @TempIds
             )
    SELECT  T.*
    FROM    cte
            INNER JOIN @Temp T ON [T].ID = cte.ID
    UNION
    SELECT  T1.*
    FROM    #TempTable TempTable
            INNER JOIN @Temp T1 ON [TempTable].ID = T1.ID

  DROP TABLE #TempTable  

输出:

ID          NAME                           PARENTID    STATUS
----------- ------------------------------ ----------- ------
1           Folder A                       0           0
2           Folder B                       1           0
3           Folder C                       2           1
4           Folder D                       1           0
5           Folder E                       4           0
6           Folder G                       5           1

答案 1 :(得分:0)

我做了一个递归CTE - 我从底部开始,任何没有孩子的文件夹。从那里开始,我会在“GOOD”列中遇到“1”状态,并且清除从底部开始创建的重复项。

;WITH CTE AS 
(
    SELECT ID, NAME, PARENTID, STATUS GOOD, STATUS
    FROM @Temp T1
    WHERE NOT EXISTS (SELECT * FROM @Temp T2 WHERE T2.PARENTID = T1.ID)

    UNION ALL

    SELECT T.ID, T.NAME, T.PARENTID, T.STATUS | C.GOOD GOOD, T.STATUS
    FROM @Temp T
    JOIN CTE C
    ON C.PARENTID = T.ID
)

SELECT DISTINCT ID, NAME, PARENTID, STATUS FROM CTE
WHERE GOOD = 1
ORDER BY ID ASC