Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest way to do a recursive self-join?

What is the simplest way of doing a recursive self-join in SQL Server? I have a table like this:

PersonID | Initials | ParentID 1          CJ         NULL 2          EB         1 3          MB         1 4          SW         2 5          YT         NULL 6          IS         5 

And I want to be able to get the records only related to a hierarchy starting with a specific person. So If I requested CJ's hierarchy by PersonID=1 I would get:

PersonID | Initials | ParentID 1          CJ         NULL 2          EB         1 3          MB         1 4          SW         2 

And for EB's I'd get:

PersonID | Initials | ParentID 2          EB         1 4          SW         2 

I'm a bit stuck on this can can't think how to do it apart from a fixed-depth response based on a bunch of joins. This would do as it happens because we won't have many levels but I would like to do it properly.

Thanks! Chris.

like image 972
Chris Avatar asked Nov 18 '09 16:11

Chris


People also ask

What is recursive self join?

Recursive joins are sometimes also called “fixed-point joins”. They are used to obtain the parent-child data. In SQL Recursive joins are implemented with recursive common table expressions. Recursive common table expression (CTEs) is a way to reference a query over and over again.

What is a recursive join example?

For example, if a database of family relationships is to be searched, and the record for each person has "mother" and "father" fields, a recursive join would be one way to retrieve all of a person's known ancestors: first the person's direct parents' records would be retrieved, then the parents' information would be ...

How do I create a recursive query in SQL?

Recursion is achieved by WITH statement, in SQL jargon called Common Table Expression (CTE). It allows to name the result and reference it within other queries sometime later. Here is a sample. Query (SELECT 1 AS n) now have a name — R .

How do you implement a self join?

To use a self join, the table must contain a column (call it X) that acts as the primary key and a different column (call it Y) that stores values that can be matched up with the values in Column X. The values of Columns X and Y do not have to be the same for any given row, and the value in Column Y may even be null .


1 Answers

WITH    q AS          (         SELECT  *         FROM    mytable         WHERE   ParentID IS NULL -- this condition defines the ultimate ancestors in your chain, change it as appropriate         UNION ALL         SELECT  m.*         FROM    mytable m         JOIN    q         ON      m.parentID = q.PersonID         ) SELECT  * FROM    q 

By adding the ordering condition, you can preserve the tree order:

WITH    q AS          (         SELECT  m.*, CAST(ROW_NUMBER() OVER (ORDER BY m.PersonId) AS VARCHAR(MAX)) COLLATE Latin1_General_BIN AS bc         FROM    mytable m         WHERE   ParentID IS NULL         UNION ALL         SELECT  m.*,  q.bc + '.' + CAST(ROW_NUMBER() OVER (PARTITION BY m.ParentID ORDER BY m.PersonID) AS VARCHAR(MAX)) COLLATE Latin1_General_BIN         FROM    mytable m         JOIN    q         ON      m.parentID = q.PersonID         ) SELECT  * FROM    q ORDER BY         bc 

By changing the ORDER BY condition you can change the ordering of the siblings.

like image 176
Quassnoi Avatar answered Oct 14 '22 04:10

Quassnoi