6

こんにちは、私はテーブルを持っていると言います:

Person:
PersonId
Name
ManagerId

したがって、ManagerId は別の人への参照です。

したがって、データベースに人物が存在する可能性があります。

1
Bob
null

2
Steve
1

3
Tim
2

したがって、Bob は Steve のマネージャーであり、Steve は Tim のマネージャーです。

そこで私がやりたかったのは、ボブの管理下にあるすべての人を取得するクエリを作成することです。直接的または間接的に。だから私はスティーブとティムの両方を手に入れたいと思っています. 同じ列に並んでいます。

私が書く場合:

select * from Person
where ManagerId = 1 I would get only Steve.

直接的または間接的に全員をボブの下に置くにはどうすればよいでしょうか?

4

3 に答える 3

6

この問題を解決するには、共通テーブル式 (CTE) を使用できます。Andrei が指摘したように、CTE は再帰に使用できます (Andrei が投稿に含めた優れたリファレンスを参照してください)。次のようなテーブルがあるとします。

create table Person
(
   PersonId int primary key,
   Name varchar(25),
   ManagerId int foreign Key references Person(PersonId)
)

次のデータをテーブルに挿入しましょう。

insert into Person (PersonId, Name, ManagerId) values 
    (1,'Bob', null),
    (2, 'Steve',1),
    (3, 'Tim', 2)
    (4, 'John', 3),
    (5, 'James', null),
    (6, 'Joe', 5)

次に、Bob に直接的または間接的に報告する全員 (Steve、Tim、および John) を返すクエリが必要です。James と Bob は誰にも報告しないため、または Joe は James に報告するため、返したくありません。これは、次のように CTE クエリで実行できます。

WITH Managers AS 
( 
     --initialize
     SELECT PersonId, Name, ManagerId  
        FROM Person WHERE ManagerId =1
     UNION ALL 
     --recursion 
     SELECT p.PersonId, p.Name, p.ManagerId 
        FROM Person p INNER JOIN Managers m  
        ON p.ManagerId = m.PersonId 
) 
SELECT * FROM Managers

このクエリは正しい結果を返します。

PersonId    Name                      ManagerId
----------- ------------------------- -----------
2           Steve                     1
3           Tim                       2
4           John                      3

編集:この回答は、OP が SQL Server 2005 以降を使用していると仮定して有効です。この構文が MySQL または Oracle で有効かどうかはわかりません。

于 2012-05-27T23:52:32.037 に答える
0

MS SQL Server 2005以降を使用している場合は、@ AndrewDrynovが指摘したように、次のようにCTEを使用できます。

;WITH Emps(PersonId, Name, PersonLevel, ManagerName)
AS
(
    SELECT PersonId, Name, 0 AS PersonLevel, 
           CONVERT(NVARCHAR(50), 'No Manager') AS ManagerName
    FROM Persons
    WHERE ManagerId IS NULL
    Union All
    SELECT p.PersonId, P.Name, e.PersonLevel + 1 , e.Name 
    FROM Persons p 
    INNER JOIN Emps e ON p.ManagerId = e.PersonId 
 ) 
SELECT * 
FROM Emps 
WHERE PersonLevel <= 2

このクエリにより、次のようになります。

  PersonId   |   Name  |  Peroson Level   |   Manager
 ------------+---------+------------------+--------------
     1           Bob           0             No Manager
     2          Steve          1                Bob
     3           Tim           2               Steve

ここで実際の動作を確認できます。

デモ

于 2012-05-27T23:48:44.127 に答える
0
select * 
from Person A 
inner join Person B ON B.PersonID = A.ManagerID
where ManagerId = 1
于 2012-05-28T00:36:14.863 に答える