如何在 SQL 中获得树的第三层

How to get the third level of a tree in SQL

我的目标是使用SQL服务器列出一个家庭的第四代。

图中的示例家谱(基于 id)

FAMILY TREE

我的表格是:

家庭

+------+-----------------+
| f_id | f_name          |
+------+-----------------+
| 1    | Name Surname 1  |
| 2    | Name Surname 2  |
| 3    | Name Surname 3  |
| 4    | Name Surname 4  |
| 5    | Name Surname 5  |
| 6    | Name Surname 6  |
| 7    | Name Surname 7  |
| 8    | Name Surname 8  |
| 9    | Name Surname 9  |
| 10   | Name Surname 10 |
+------+-----------------+

关系

+----------+---------+
| r_parent | r_child |
+----------+---------+
| 1        | 2       |
| 1        | 3       |
| 2        | 4       |
| 2        | 5       |
| 3        | 6       |
| 3        | 7       |
| 3        | 8       |
| 7        | 9       |
| 8        | 10      |
+----------+---------+

这是我需要的结果:

 9 Name Surname
10 Name Surname

对于固定数量(且相对较少)的级别,您可以加入:

select f.*
from relations r1
inner join relations r2 on r2.r_parent = r1.r_child
inner join relations r3 on r3.r_parent = r2.r_child
inner join family f on f.f_id = r3.r_child
where not exists (select 1 from relations r0 where r0.r_child = r1.r_parent)

更通用的方法是使用递归查询:

with cte as (
    select r.r_parent, r.r_child, 1 lvl
    from relations r
    where not exists (select 1 from relations r0 where r0.r_child = r.r_parent)
    union all 
    select r.r_parent, r.r_child, c.lvl + 1
    from relations r
    inner join cte c on c.r_child = r.r_parent
    where c.lvl < 3
)
select f.*
from family f
inner join cte c on c.r_child = f.f_id
where c.lvl = 3

您需要使用不同的别名进行相同的连接以获得最后一代 另一种选择是进行递归 CTE。

SELECT 
    G4.*
FROM relations GR1
    INNER JOIN family G1 ON GR1.r_parent = G1.f_id
    INNER JOIN family G2 on GR1.r_child = G2.f_id
    INNER JOIN relations GR2 ON GR2.r_parent = G2.f_id
    INNER JOIN family G3 ON GR2.r_child = G3.f_id
    INNER JOIN relations GR3 ON GR3.r_parent = G3.f_id
    INNER JOIN family G4 ON GR3.r_child = G4.f_id

使用的脚本是:

CREATE TABLE family(f_id int ,f_name nvarchar (200))
INSERT INTO family 
VALUES 
  (1, 'Name Surname 1')
, (2, 'Name Surname 2')
, (3, 'Name Surname 3')
, (4, 'Name Surname 4')
, (5, 'Name Surname 5')
, (6, 'Name Surname 6')
, (7, 'Name Surname 7')
, (8, 'Name Surname 8')
, (9, 'Name Surname 9')
, (10, 'Name Surname 10')

CREATE TABLE relations (r_parent int, r_child int)
INSERT INTO relations VALUES (1, 2), (1, 3), (2,4), (2,5), (3,6), (3,7), (3,8), (7,9), (8,10)



SELECT 
    G4.*
FROM relations GR1
    INNER JOIN family G1 ON GR1.r_parent = G1.f_id
    INNER JOIN family G2 on GR1.r_child = G2.f_id
    INNER JOIN relations GR2 ON GR2.r_parent = G2.f_id
    INNER JOIN family G3 ON GR2.r_child = G3.f_id
    INNER JOIN relations GR3 ON GR3.r_parent = G3.f_id
    INNER JOIN family G4 ON GR3.r_child = G4.f_id


DROP TABLE family
DROP TABLE relations