Reputation: 12749
I have a Location table:
Id int
MasterLocationId int
Name varchar(50)
A location can have a master location and so on. There's no specific limit to how many levels this could be.
How can I search for any locations with a certain ID, or locations where a master record has that ID, or its master record has that ID - and so on.
I'm not really sure what to even search for on Google here - perhaps this type of situation has a name and I'm not sure what it's called?
I've searched for recursive TSQL and couldn't find anything.
Is this possible?
Thanks
Upvotes: 0
Views: 73
Reputation: 679
As @Isaac and @Jeroen said in comments, recursive CTE is what you need.
Sample data:
CREATE TABLE Locations (
Id int,
MasterLocationId int,
Name varchar(50)
);
insert into Locations (Id, Name, MasterLocationId)
values
(1, 'Alice', null),
(2, 'Bob', 1),
(3, 'Charlie', 2),
(4, 'Dave', 3),
(5, 'Erin', 4),
(6, 'Frank', 5),
(7, 'Grace', 6),
(8, 'Heidi', 7),
(9, 'Ivan', 8),
(10,'Judy', 9),
(11,'Kevin', 10),
(12,'Lucy', 6),
(13,'Mike', 7),
(14,'Noah', 8),
(15,'Olivia', 9),
(16,'Peggy', 10),
(17,'Rupert', 6),
(18,'Sybil', 7),
(19,'Ted', 8),
(20,'Trudy', 9),
(21,'Uma', 10),
(22,'Victor', 11),
(23,'Walter', 22),
(24,'Xavier', 23),
(25,'Yves', 24),
(26,'Zoe', 25);
And a query:
;
with Locations_CTE as (
-- anchor of 1st tier parents
select L1.Id, L1.Name, L1.MasterLocationId, L2.Name as MasterLocationName, 1 as MasterLocationTier
from Locations as L1
left join Locations as L2
on L1.MasterLocationId = L2.Id
-- recursive part
union all
select L1.Id, L1.Name, L2.MasterLocationId, L3.Name as MasterLocationName, L1.MasterLocationTier + 1 as MasterLocationTier
from Locations_CTE as L1
inner join Locations as L2
on L1.MasterLocationId = L2.Id
inner join Locations as L3
on L2.MasterLocationId = L3.Id
)
select *
from Locations_CTE
where MasterLocationId = 11 -- Find all locations which have Kevin as MasterLocation somewhere in a hierarchy.
or Id = 11 -- And full hierarchy for Kevin
order by Id, MasterLocationTier
Upvotes: 2