T-SQL层次结构查询

时间:2017-12-05 18:06:44

标签: sql-server loops tsql hierarchy common-table-expression

我有一个包含分层数据的表: enter image description here

这是包含id,父ID,名称,代码(有时未填充),level和isroot列的数据示例。在实际场景中,将有更多级别,而不仅仅是2,但现在让我们看一下简化示例。

我需要做的是循环遍历所有记录,并在层次结构的任何级别找到未填充id的行:

  • 具有id范围的行应该从6到10返回,因为它们没有在层次结构的任何位置填写代码
  • 不应返回从1到5的行,因为在层次结构中的某处提到了代码。

如何用T-SQL解决这个问题?

我想到的唯一解决方案是递归(cte或WHILE),但我想要实现的是太复杂而且没有解决问题。

2 个答案:

答案 0 :(得分:1)

与@ DhruvJoshi的答案略有不同,因为它可能有用:

WITH recCTE AS
(
    SELECT 
        id, 
        parent_id, 
        CASE WHEN CODE IS NOT NULL THEN 1 ELSE 0 END as code_check,
        1 as depth,
        CAST(id as VARCHAR(50)) as path
    FROM table
    WHERE isRootLevel = 1
    UNION ALL
    SELECT
        table.id,
        table.parent_id,
        CASE WHEN CODE IS NOT NULL OR reccte.code_check = 1 THEN 1 ELSE 0 END,
        depth + 1 as depth,
        reccte.path + CASE(table.id AS varchar(10)) as path
    FROM
        recCTE 
        INNER JOIN table ON
            recCTE.ID = table.parent_id
    WHERE depth < 20 /*just in case you start cycling/endless looping*/
)
SELECT * FROM recCTE where code_check = 0 ORDER BY path, depth;

答案 1 :(得分:0)

这样的查询应该有效:

; with cte as 
(
select id, parent_id,code,parent_id as RootId from tableT where IsRootLevel=1
UNION ALL
select T2.id,T2.parent_id,T2.code,T1.RootId as RootId from tableT T2 join
cte T1 on T1.id=T2.parent_id and IsRootLevel=0
)   
,
cte2 as
(select id,MAX(case when code ='' then NULL else code end) over( partition by RootId) as code from cte)

select T1.* from tableT T1 left join cte2 T2 
on T1.id=T2.id
where T2.code is NULL

See working demo