我有一个Locations表,它使用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 :(得分: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
);