2013-07-29 76 views
0

我有一個使用HIERARCHYID列映射城市/地區/國家/大洲位置表。該表看起來像這樣:使用HIERARCHYID找到葉節點

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'); 

我有第二張表,將事件映射到位置。該表格使層次結構變得平坦,並且每個層次都有一條記錄(我通過這種方式繼承了它)。所以,如果一個事件是在洛杉磯,有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 

回答

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 

編輯:使用

一個簡單的版本NOT EXISTS,而不是一個LEFT JOIN的CTE:

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 
      ); 
+0

這不正是我一直在尋找。我正在嘗試使用@Locations層次結構來查找每個事件的葉節點。我認爲我做了很好的工作,包括數據填充:) –

+0

沒錯表變量,創建/插入到表變量是便攜,易於使用。當我看時,我可以發誓他們不在那裏。可能是我。道歉,如果他們在那裏開始,我錯過了他們。編輯好的代碼(針對區分大小寫的方法名稱進行調整,並對EventLocations進行不完整連接)返回您在問題中指定的集合。 HTH – JAQFrost

+0

太棒了。正是我需要的。謝謝。 –