1

Group テーブルがあり、そのテーブル内には、Group テーブル内のグループの親を示す ParentId 列があります。目的は、これらのグループから動的メニューを構築することです。最後の子をループして取得し、結果セットを作成できることはわかっていますが、これを実現するためのより SQL 的な方法があるかどうかに興味があります。

テーブルには、int、int、および varchar の Id、ParentId、および Title フィールドがあります。

基本的に、階層は次のように構築できます (People が基本グループです)。

People -> Male   -> Boy
                 -> Man
       -> Female

各ブランチの最後の子を取得したい。つまり、この場合は {Boy, Man, Female} です。

前述したように、その情報を取得することは問題ではありません。基本的に基本グループを変更し、階層全体を外側に動的にトラバースできる、一連のユニオンとループを作成する必要なく、それを取得するより良い方法を探しています。私は本当にDbの男ではないので、これを行うための巧妙な方法があるかどうかはわかりません.

4

2 に答える 2

4

多くの階層の 1 つのリーフ レベルを取得するには、再帰的共通テーブル式(CTE) を使用して階層を列挙し、どのメンバーが別のグループの親ではないかをチェックして、リーフにフィルターをかけます。

Declare @RootID int = 1

;with cte as (
  select 
    Id,
    ParentId,
    Title
  From
    Groups
  Where
    Id = @RootID
  Union All
  Select
    g.Id, 
    g.ParentId,
    g.Title
  From
    cte c
      Inner Join
    Groups g
      On c.Id = g.ParentID
)
Select
  *
From
  cte g
Where
  Not Exists (
    Select
      'x'
    From
      Groups g2
    Where
      g2.ParentID = g.Id
  );

存在しないのではなく、左の結合でこれを行うこともできます

http://sqlfiddle.com/#!6/8f1aa/9

于 2012-11-26T22:20:56.000 に答える
1

hierarchyidSQL Server 2012を使用しているので、 ;を利用できます。これは、ローレンスのスキーマに従った例です。

CREATE TABLE Groups
    (
      Id INT NOT NULL
             PRIMARY KEY
    , Title VARCHAR(20)
    , HID HIERARCHYID
    )

INSERT  INTO Groups
VALUES  ( 1, 'People', '/' ),
        ( 2, 'Male', '/1/' ),
        ( 3, 'Female', '/2/' ),
        ( 4, 'Boy', '/1/1/' ),
        ( 5, 'Man', '/1/2/' );

SELECT  Id
      , Title
FROM    Groups
WHERE   HID NOT IN ( SELECT HID.GetAncestor(1)
                     FROM   Groups
                     WHERE  HID.GetAncestor(1) IS NOT NULL )

http://sqlfiddle.com/#!6/00330/1/0

結果:

ID  TITLE
3   Female
4   Boy
5   Man
于 2012-11-26T22:41:20.033 に答える