我有下表:
位置:
ID Name Depth ParentID HierachyPath ContactID
1 US 0 NULL \ 25
2 Florida 1 1 \001 NULL
3 Miami 2 2 \001\001 NULL
4 Dade County 3 3 \001\001\001 NULL
5 Orlando 2 2 \001\002 15
6 County1 3 3 \001\002\001 12
我将获得一个位置ID,例如4.我将立即将多个位置ID传递给我,因此我可能需要一次找到1个位置或1000个位置的联系人。如果在位置4处没有联系人,我需要沿着HierachyPath向上行进,直到找到联系人。关于如何做到这一点的任何想法?
答案 0 :(得分:1)
您可以使用递归公用表表达式向上走,直到找到具有联系人的父级。例如:
; with CTE as
(
select ID
, ContactID
, ParentID
, ID BaseID
, 1 as Level
from Location
where ID in (4,5)
union all
select parent.ID
, parent.ContactID
, parent.ParentID
, child.BaseID
, child.Level + 1
from Location parent
join CTE child
on parent.ID = child.ParentID
-- Stop when we have a contact
where child.ContactID is null
)
select CTE.BaseID as ID
, CTE.ContactID
from CTE
where ContactID is not null;
答案 1 :(得分:0)
我不确定您的数据是否正确,因为佛罗里达州在给定的数据列表中没有ParentId。我认为以下查询将为您提供所需的结果。使用CTE
declare @myId int = 4
;with cte as (
select id,pid, cid
from L where id = @myId
union all
select L.id,L.pid,L.cid
from cte join L on cte.pid = L.id
where cte.cid is null
)
select top (1) cid from cte
order by pid
仅当您传递单个ID时才有效,而不是您更新的问题。几乎没有什么变化可以使它适用于此。 @Andomar已经解决了上述问题。
答案 2 :(得分:0)
我添加了第二个解决方案(多个ID)
第一个解决方案
CREATE TABLE CocoJamboTable (
ID INT PRIMARY KEY,
Name NVARCHAR(50) NOT NULL,
HierachyPath HIERARCHYID NOT NULL,
ContactID INT NULL -- REFERENCES .... (ContactID)
);
INSERT INTO dbo.CocoJamboTable (ID, Name, HierachyPath, ContactID)
VALUES
(1, 'US ', '/', 25)
,(2, 'Florida ', '/1/', NULL)
,(3, 'Miami ', '/1/1/', NULL)
,(4, 'Dade County ', '/1/1/1/', NULL)
,(5, 'Orlando ', '/1/2/', 15)
,(6, 'County1 ', '/1/2/1/', 12);
CREATE UNIQUE INDEX IUN_CocoJamboTable_HierachyPath_#_ContactID
ON dbo.CocoJamboTable(HierachyPath)
INCLUDE (ContactID);
GO
DECLARE @ID INT=4;
DECLARE @ContactID INT =
(
SELECT d.ContactID
FROM (
SELECT c.ContactID,
ROW_NUMBER() OVER(
ORDER BY CASE WHEN c.ContactID IS NOT NULL THEN 1 ELSE 2 END, -- First: NOT NULL ContacIDs
b.Number ASC
) AS RowNum
FROM dbo.CocoJamboTable a
JOIN (VALUES (0),(1),(2),(3),(5),(6),(7),(8),(9),(10)) b(Number) ON a.HierachyPath.GetLevel() >= b.Number
JOIN dbo.CocoJamboTable c WITH(FORCESEEK) ON c.HierachyPath=a.HierachyPath.GetAncestor(b.Number)
-- FORCESEEK: For some reason, the index (IUN_CocoJamboTable_HierachyPath_#_ContactID) is not used by default
WHERE a.ID=@ID
) d
WHERE d.RowNum=1
);
SELECT @ContactID AS [@ContactID];
SELECT a.ID,
c.ContactID,
a.HierachyPath.ToString() AS HierachyPathAsString,
a.HierachyPath.GetLevel() AS HierachyPathGetLevel,
b.Number,
a.HierachyPath.GetAncestor(b.Number).ToString() AS HierachyPathGetAncestor_n_Number
FROM dbo.CocoJamboTable a
JOIN (VALUES (0),(1),(2),(3),(5),(6),(7),(8),(9),(10)) b(Number) ON a.HierachyPath.GetLevel() >= b.Number
JOIN dbo.CocoJamboTable c ON c.HierachyPath=a.HierachyPath.GetAncestor(b.Number)
WHERE a.ID=@ID
ORDER BY b.Number DESC
结果:
@ContactID
-----------
25
ID ContactID HierachyPathAsString HierachyPathGetLevel Number HierachyPathGetAncestor_n_Number
-- --------- -------------------- -------------------- ----------- --------------------------------
4 25 /1/1/1/ 3 3 /
4 NULL /1/1/1/ 3 2 /1/
4 NULL /1/1/1/ 3 1 /1/1/
第二个解决方案(多个ID)
DECLARE @IDs TABLE (ID INT PRIMARY KEY);
INSERT @IDs
VALUES (4), (5), (6);
SELECT *
FROM @IDs v
OUTER APPLY
(
SELECT d.ContactID
FROM (
SELECT c.ContactID,
ROW_NUMBER() OVER(
ORDER BY CASE WHEN c.ContactID IS NOT NULL THEN 1 ELSE 2 END, -- First: NOT NULL ContacIDs
b.Number ASC
) AS RowNum
FROM dbo.CocoJamboTable a
JOIN (VALUES (0),(1),(2),(3),(5),(6),(7),(8),(9),(10)) b(Number) ON a.HierachyPath.GetLevel() >= b.Number
JOIN dbo.CocoJamboTable c WITH(FORCESEEK) ON c.HierachyPath=a.HierachyPath.GetAncestor(b.Number)
-- FORCESEEK: For some reason, the index (IUN_CocoJamboTable_HierachyPath_#_ContactID) is not used by default
WHERE a.ID=v.ID
) d
WHERE d.RowNum=1
) oa;