0

都市/地域/国/大陸をマッピングするために hierarchyid 列を使用する Locations テーブルがあります。テーブルは次のようになります。

declare @Locations table (
  LocationNodeID hierarchyid,
  LocationID int,
  LocationName varchar(50)
)

insert into @Locations (LocationNodeID, LocationID, LocationName) values
  (cast('/0/' as hierarchyid), 1, 'World'),
  (cast('/0/1/' as hierarchyid), 2, 'North America'),
  (cast('/0/1/1/' as hierarchyid), 3, 'United States'),
  (cast('/0/1/1/1/' as hierarchyid), 4, 'California'),
  (cast('/0/1/1/1/1/' as hierarchyid), 5, 'Los Angeles'),
  (cast('/0/1/1/1/2/' as hierarchyid), 6, 'San Francisco'),
  (cast('/0/1/1/2/' as hierarchyid), 7, 'Ohio'),
  (cast('/0/1/1/2/1/' as hierarchyid), 8, 'Cleveland'),
  (cast('/0/1/1/2/2/' as hierarchyid), 9, 'Toledo');

イベントを場所にマップする 2 つ目のテーブルがあります。このテーブルは階層を平坦化し、レベルごとに 1 つのレコードを持ちます (この方法で継承しました)。したがって、イベントがロサンゼルスで行われる場合、このテーブルにはイベントの 4 つのレコード (ロサンゼルス、カリフォルニア、米国、北米) があります。同じイベントを複数の場所で開催することもできます。

declare @EventLocations table (
  EventID int,
  LocationID int
)

insert into @EventLocations (EventID, LocationID) values
  (1, 2),  -- North America
  (1, 3),  -- United States
  (1, 4),  -- California
  (1, 5),  -- Los Angeles (leaf)

  (2, 2),  -- North America
  (2, 3),  -- United States
  (2, 7),  -- Ohio (leaf)

  (3, 2),  -- North America
  (3, 3),  -- United States (leaf)

  (4, 2),  -- North America
  (4, 3),  -- United States
  (4, 4),  -- California (leaf)
  (4, 7),  -- Ohio
  (4, 9);  -- Toledo (leaf)

リーフ ノードとして識別した @EventLocations からレコードを選択するクエリを作成しようとしています。これらは、@Locations 階層に関連する子孫を持たないイベントごとのレコードです。したがって、場所が @EventLocations の「葉」である可能性がありますが、@Locations に子孫があります。以下のクエリを試してみましたが、@Locations テーブルのリーフであるレコードのみが抽出されます。

select ep.EventID, p.*, p2.*
from @EventLocations ep
  inner join @Locations p on ep.LocationID = p.LocationID
  left outer join @Locations p2 on p.LocationNodeID = p2.LocationNodeID.GetAncestor(1)
where p2.LocationID is null
order by ep.EventID, ep.LocationID
4

1 に答える 1

0

以下のクエリのようなものを探していると思います。私がきちんとあなたをフォローしているなら、あなたは同じイベントで両親を探す必要があります.

ところで、通常はサンプル データとスキーマ情報を提供する必要があります。これにより、サポートが容易になり、提案したコードをテストできるようになります。

WITH el AS
    (
        SELECT
            e.eventid
            , l.locationid
            , l.locationnodeid
            , l.locationnodeid.GetAncestor(1) parent
        FROM 
            @EventLocations e
        JOIN
            @Locations l
            ON 
                l.locationid = e.locationid
    )
SELECT
    ep.eventid
    , p.*
FROM 
    el
JOIN
    @EventLocations ep
    ON 
        ep.eventid = el.eventid
        AND 
        ep.locationid = el.locationid
JOIN
    @Locations p
    ON 
        p.locationid = ep.locationid
LEFT JOIN
    el e2
    ON 
        el.eventid = e2.eventid
        AND e2.parent = el.locationnodeid
WHERE
    e2.eventid IS NULL

編集:

CTE への LEFT JOIN ではなく、NOT EXISTS を使用した単純なバージョン:

    SELECT
        ep.EventID
        , p.*
    FROM 
        @EventLocations ep
    JOIN
        @Locations p
        ON 
            p.locationid = ep.locationid    
    WHERE
        NOT EXISTS
            (
                SELECT 
                    NULL
                FROM 
                    @EventLocations el2
                JOIN 
                    @Locations l2
                    ON l2.LocationID = el2.LocationID
                WHERE
                    el2.EventID = ep.EventID
                    AND
                    l2.LocationNodeID.GetAncestor(1) = p.locationnodeid
            );
于 2013-08-01T16:22:43.313 に答える