0

我有一个如下表:

ID         Type      ParentID
001         C          007
002         C          005
003         B          007
004         C          008
005         R          NULL
006         C          004
007         B          004
008         R          009
009         X          NULL

类型层次结构是 X>R>C=B。我需要找到 B 和 C 的所有记录的 R 父级。挑战是一些 B 或 C 记录的父级是 B 或 C 并且需要排除 X。结果将是:

ID         Type      ParentID     MasterParentID
001         C          007           008
002         C          005           005
003         B          007           008
004         C          008           008
005         R          NULL          NULL
006         C          004           008
007         B          004           008 
008         R          009           NULL
009         X          NULL          NULL

有什么建议么?非常感激。

4

3 回答 3

1

你需要递归 CTE:

with cte1 as (
    select
       T.ID, T.Type, T.ParentID,
       case
          when T2.Type = 'X' then cast(null as varchar(3))
          else T.ParentID
       end as MasterParentID
    from Table1 as T
        left outer join Table1 as T2 on T2.ID = T.ParentID
), cte2 as (
    select
        T.ID, T.Type, T.ParentID,
        T.MasterParentID, T.ID as MasterParentID2
    from cte1 as T
    where T.MasterParentID is null

    union all

    select
        T.ID, T.Type, T.ParentID,
        c.MasterParentID2 as MAsterParentID,
        c.MasterParentID2 as MAsterParentID2
    from cte1 as T
        inner join cte2 as c on c.ID = T.MasterParentID
)
select
    T.ID, T.Type, T.ParentID, T.MasterParentID
from cte2 as T
order by ID asc

sql fiddle demo

于 2013-08-21T21:36:14.697 回答
1

在 SQL Server 2005 及更高版本中,“公用表表达式”可以做到这一点......

-- Assuming this table structure
--CREATE TABLE dbo.Test ( ID char(3), Type char(1), ParentID char(3))

;
WITH Tree(StartID, StartType, Parent, Child) AS
(
    SELECT ID, Type, cast(NULL as char(3)), ID
    FROM Test
    WHERE ParentID IS NULL

    UNION ALL

    SELECT
        -- Skip over the "X" rows...
        CASE WHEN Tree.StartType = 'X'
            THEN Test.ID
            ELSE Tree.StartID
        END,
        CASE WHEN Tree.StartType = 'X'
            THEN Test.Type
            ELSE Tree.StartType
        END,
        Test.ParentID,
        Test.ID
    FROM Test
        INNER JOIN Tree
        ON Test.ParentID = Tree.Child
)

SELECT Test.ID, Test.Type, Test.ParentID,
    CASE WHEN Tree.StartID = Test.ID
        THEN NULL
        ELSE Tree.StartID
    END AS MasterParentID
FROM Test
    LEFT OUTER JOIN Tree
    ON Test.ID = Tree.Child
ORDER BY Test.ID
于 2013-08-21T20:59:25.763 回答
1

这是使用 CTE 实现的查询,也是一个工作演示

  ;with Childs as
  (
      select ID, Type, ParentID, 0 Level
      from SomeHierarchy
      union all
      select Childs.ID, SomeHierarchy.Type, SomeHierarchy.ParentID, Childs.Level + 1 Level
      from 
          SomeHierarchy
          inner join Childs on Childs.ParentID = SomeHierarchy.ID
      where
          SomeHierarchy.Type not in ('R', 'X')

  )
  select 
    SomeHierarchy.ID, SomeHierarchy.Type, SomeHierarchy.ParentID, NewChilds.ParentID MasterParentID
  from SomeHierarchy
    inner join (
                  select *, Row_Number() over(Partition by ID order by Level desc)  RowNum
                  from Childs
                  where
                    ParentID is not null or Level = 0
                ) NewChilds on NewChilds.ID = SomeHierarchy.ID
  where
    NewChilds.RowNum = 1
于 2013-08-21T21:01:20.630 回答