使用T-SQL在分层数据中查找特定的父级

Ram*_*ona 4 sql t-sql sql-server hierarchical-data

我有按层次结构排列的对象。每个对象都有一个ID,一个父对象(TO_ID在表中)和一个类型。我的数据在一个如下表中:

ID  | TO_ID | TYPE
123 | 103   | group
176 | 103   | field
256 | 169   | group
103 | 234   | organization
234 | 390   | site
Run Code Online (Sandbox Code Playgroud)

现在,我要搜索表,直到找到具有特定类型的父对象(我不知道我的起始对象有多少个父对象)。

例如,我以开头,ID 123并希望通过找到ID父对象的TYPE site

如何使用SQL解决此问题?

Sal*_*n A 5

为此,您需要递归CTE:

DECLARE @t TABLE (ID INT, TO_ID INT, TYPE VARCHAR(100));

INSERT INTO @t VALUES
(123, 103, 'group'),
(176, 103, 'field'),
(256, 169, 'group'),
(103, 234, 'organization'),
(234, 390, 'site'),
(390, 999, 'notme');

DECLARE @start INT = 123;
DECLARE @stop VARCHAR(100) = 'site';

WITH cte AS (
    SELECT base.*, 1 AS LVL
    FROM @t base
    WHERE ID = @start
    UNION ALL
    SELECT curr.*, LVL + 1
    FROM @t curr
    INNER JOIN cte prev ON curr.ID = prev.TO_ID
    WHERE prev.TYPE <> @stop
)
SELECT *
FROM cte
ORDER BY LVL
Run Code Online (Sandbox Code Playgroud)

递归CTE实际上是一个迭代查询。您从一些行(第123行)开始,然后继续将行追加到上一个迭代的结果中,直到满足某些条件为止(您用完了行或site在上一个迭代中找到了行)。结果如下:

ID  | TO_ID | TYPE         | LVL
123 | 103   | group        | 1
103 | 234   | organization | 2
234 | 390   | site         | 3
Run Code Online (Sandbox Code Playgroud)

如果您对查找两个节点之间的完整路径不感兴趣,请从curr中删除where子句,并WHERE TYPE = site在最后添加。