0

ロールアップ入力に基づいて、同じテーブルに親アカウントとその子アカウントを返す t-sql クエリを作成しようとしています。誰か助けてくれませんか?

***TABLE:USERS*** 
 UserId  ParentId  
 66      -1
 67      -1
 68      -1
 69      54
 70      55
 71      56
 72      57

これは私がこれまでに持っているものですが、最後のアカウントである 1 つのアカウントのみを返します。再帰に ParentId を含める必要があるため、親アカウントと子アカウントのリストが次々に取得されます。

    DECLARE @RollUp AS bit 
    DECLARE @ParentID As INT 
    SELECT @RollUp = 0 
         If @Rollup = 1 SELECT @ParentID = CASE WHEN ParentID = -1 
         THEN Users.USER_ID 
         Else ParentID END 
    FROM Users WHERE user_Id  IN (70,71) ELSE 
    SELECT @ParentID = Users.USER_ID 
    FROM Users WHERE USER_Id  IN (70,71) ;
    WITH TRAVERSE_TREE_CTE AS 
    (  
    Select User_ID,ParentID 
    FROM Users 
    WHERE User_ID = @ParentID 
    UNION ALL Select Users.User_ID, Users.ParentID 
    FROM TRAVERSE_TREE_CTE INNER 
    JOIN Users 
    ON TRAVERSE_TREE_CTE.User_ID = Users.ParentID
    )
    Select * from Users 
    where User_id IN (SELECT distinct User_ID FROM TRAVERSE_TREE_CTE)
4

1 に答える 1

0

再帰で絶対を参照していることが問題だと思います。

Where User_ID = @ParentID

述語は通常中ではなく、再帰部分の後に行います。場合によっては、再帰式の絶対式を使用すると、明示的に配置して 1 つのインスタンスのみでその親に結合しようとしているため、一般に予測できない結果が生じることがあります。しかし、探している再帰のレベルと、そのレベルが決定された後の述語を式に伝える必要があることもよくあります。

これは、役立つ可能性のある自己入力の例です。最大再帰レベルを探し、そのレベルのみを決定します。

Declare @table table ( PersonId int identity, PersonName varchar(512), Account int, ParentId int, Orders int);

insert into @Table values ('Brett', 1, NULL, 1000),('John', 1, 1, 100),('James', 1, 1, 200),('Beth', 1, 2, 300),('John2', 2, 4, 400);

select 
    PersonID
,   PersonName
,   Account
,   ParentID
from @Table

; with recursion as 
    (
    select 
        t1.PersonID
    ,   t1.PersonName
    ,   t1.Account
    --, t1.ParentID
    ,   cast(isnull(t2.PersonName, '')
            + Case when t2.PersonName is not null then '\' + t1.PersonName else t1.PersonName end
            as varchar(255)) as fullheirarchy
    ,   1 as pos
    ,   cast(t1.orders + 
            isnull(t2.orders,0) -- if the parent has no orders than zero
            as int) as Orders
    from @Table t1
        left join @Table t2 on t1.ParentId = t2.PersonId
    union all
    select 
        t.PersonID
    ,   t.PersonName
    ,   t.Account
    --, t.ParentID
    ,   cast(r.fullheirarchy + '\' + t.PersonName as varchar(255))
    ,   pos + 1  -- increases
    ,   r.orders + t.orders
    from @Table t
        join recursion r on t.ParentId = r.PersonId
    )
, b as 
    (
    select *, max(pos) over(partition by PersonID) as maxrec  -- I find the maximum occurrence of position by person
    from recursion
    )
select *
from b
where pos = maxrec  -- finds the furthest down tree
-- and Account = 2  -- I could find just someone from a different department

更新しました

変数 ID に関連する子要素を表示したいだけの場合は、再帰を使用せずにテーブルを結合して戻すことができます。

Declare @table table ( PersonId int identity, PersonName varchar(512), Account int, ParentId int, Orders int);

insert into @Table values ('Brett', 1, NULL, 1000),('John', 1, 1, 100),('James', 1, 1, 200),('Beth', 1, 2, 300),('John2', 2, 4, 400);

declare @Id int = 1  -- set to 1, 2, 3, 4, 5

select 
    a.PersonName
,   isnull(b.PersonName,'No Child') as [ChildName(s)]
from @table a 
    left join @table b on a.Personid = b.ParentId
where a.PersonId = @Id
于 2013-06-10T19:01:24.550 に答える