我添加了第二个解决方案(多个 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;