niico
niico

Reputation: 12749

Match id or masterid or masterid of masterid etc

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

Answers (1)

Andrey Baulin
Andrey Baulin

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

Related Questions