0

会社の従業員のリストとその所属するチームを追加の列とともに出力するSQLServer2008クエリを作成しています。

組織ツリーの例:

Level 0: CEO
Level 1: A, B, and C
Level 2:
    For A:1,2,3
    For B:4,5,6
    For C:7,8,9

結果のセットには、名前、(ツリーの)レベル、およびチームの3つの列が表示されます。1、2、および3の場合、「A」をチーム、2をレベルと見なします。4、5、および6の場合、レベルの場合は「B」および2など。

再帰クエリを使用してツリーをナビゲートしていますが(問題はありません)、チーム名をクエリに「伝える」必要があるため(レベル8の場合は、レベル1の人が表示されます)に報告してください)、私はこれをやっています:

(...)
UNION ALL
-- Recursive Member Definition
-- in here level increments one each time, and the team should output the child
-- of the top manager
SELECT  A.treenodeid, A.parentnodeid, A.email, LEVEL+1, team = 
                                    CASE LEVEL
                                        When 1 then SET @salead = A.Email
                                        Else @salead
                                    END
   FROM XX as A 
  INNER JOIN TeamsTable as B on A.parentnodeid = b.treenodeID

CASEを使用してレベルが1かどうかを確認しようとしているので(チーム名をチームリーダーの電子メール名に更新するため)、SQLは「 SETの近くの構文が正しくない」と言い続けます。

この種の割り当てをCASEで行うことは可能ですか?私は周りを見回しましたが、これが私の再帰的なケースで機能するかどうかはわかりませんでした。

すべてのクエリは次のとおりです(ルートが「JohnSmith」であると想定)。

WITH TeamsTable (treenodeid, parentnodeid, email, Level, team)
AS
( 
    -- Anchor - Level starts with 0, and the team is empty for the top manager
    SELECT treenodeid,parentnodeid,email,0,''       
     FROM XX WHERE email = 'JohnSmith'

    UNION ALL

    -- Recursive Member Definition - in here level increments one each time, and the team should output the child of the top manager
    SELECT
        A.treenodeid, A.parentnodeid, A.email, LEVEL+1, team = 
                                CASE LEVEL
                                    When 1 then SET @salead = A.Email
                                    Else @salead
                                END
    FROM XX as A 
    INNER JOIN TeamsTable as B on A.parentnodeid = b.treenodeID
)

-- Statement that executes the CTE
SELECT *
FROM TeamsTable

どうもありがとう、みんな!

4

2 に答える 2

0

なぜ変数が必要なのですか?その後の使用は見当たりません

于 2012-10-04T18:53:08.440 に答える
0

私はこの問題にトップダウンではなく、ボトムアップで取り組みます。

チーム A、B、C、または CEO がどのチームに所属すべきかをあなたが言っていないので、私がでっちあげました。

また、サンプル データを使用可能な形式で含めました。

create table Org (
    ID int not null,
    Name varchar(10) not null,
    ParentID int null
)
go
insert into Org (ID,Name,ParentID) values
(1,'CEO',null),
(2,'A',1),
(3,'B',1),
(4,'C',1),
(5,'1',2),
(6,'2',2),
(7,'3',2),
(8,'4',3),
(9,'5',3),
(10,'6',3),
(11,'7',4),
(12,'8',4),
(13,'9',4)

クエリ:

;With AllPeople as (
    select ID,ID as LastParentID,ParentID as NextParentID, CASE WHEN ParentID is null THEN 0 ELSE 1 END as Level
    from Org
    union all
    select ap.ID,ap.NextParentID,o.ParentID,Level + 1
    from
        AllPeople ap
            inner join
        Org o
            on
                ap.NextParentID = o.ID and
                o.ParentID is not null
), Roots as (
    select ID from Org where ParentID is null
), RootedPeople as (
    select * from AllPeople where NextParentID is null or NextParentID in (select ID from Roots)
), Names as (
    select
        oself.Name,
        oteam.Name as Team,
        Level
    from
        RootedPeople rp
            inner join
        Org oself on rp.ID = oself.ID
            left join
        Org oteam on rp.LastParentID = oteam.ID
)
select * from Names

結果:

Name       Team       Level
---------- ---------- -----------
CEO        CEO        0
A          A          1
B          B          1
C          C          1
9          C          2
8          C          2
7          C          2
6          B          2
5          B          2
4          B          2
3          A          2
2          A          2
1          A          2

CTE の説明:

  • AllPeopleルートに到達するまで組織ツリーを上っていく再帰クエリです。2 つの列 (LastParentIDNextParentID) を使用して、階層の 2 つのレベルを追跡します。ルートに到達すると、その前のレベルが必要になるためです。
  • Roots親を持たないすべての人を検索します。AllPeopleこれは、完全な行を特定する方法です。
  • RootedPeople親を見つけることができなかった行、または再帰がツリーの最上部に達した行を見つける場所。
  • Names最後にテーブルに戻り、Org個人とチームに名前を割り当てます。これは必須ではありません。それ自体が最後のクエリになる可能性があります。

また、CTE が構築される再帰的な方法により、レベルを計算しながら再帰することにも注意してください。再帰するAllPeopleたびに、Levelこの行が表す に 1 を追加します。

于 2012-10-05T06:47:42.437 に答える