如何遍历树/使用SQL代码中的分层数据

时间:2011-07-11 18:31:59

标签: sql sql-server sql-server-2008

假设我有一张员工表,其中包含我公司每位员工的记录,以及一份主管专栏(如下所示)。我想准备一份报告,其中列出了监管线中每个步骤的名称和标题。例如,对于迪克罗宾斯,1d#15,我想在他的“指挥系统”中列出每个主管,一直到总统,大奶酪。我想避免使用游标,但如果这是唯一的方法,那就没关系。

id  fname   lname   title   supervisorid
1   big     cheese  president   1
2   jim     william vice president  1
3   sally   carr    vice president  1
4   ryan    allan   senior manager  2
5   mike    miller  manager 4
6   bill    bryan   manager 4
7   cathy   maddy   foreman 5
8   sean    johnson senior mechanic 7
9   andrew  koll    senior mechanic 7 
10  sarah   ryans   mechanic    8
11  dana    bond    mechanic    9
12  chris   mcall   technician  10
13  hannah  ryans   technician  10
14  matthew miller  technician  11
15  dick    robbins technician  11

真正的数据可能不会超过10级...但我宁愿不只是做10次外连接...我希望有比这更好的东西,并且比游标更少参与。

感谢您的帮助。

4 个答案:

答案 0 :(得分:20)

这基本上是我在OP评论中链接到的问题的接受答案的一个端口。

你可以使用公用表表达式

WITH Family As 
( 
    SELECT e.id, e.supervisorid, 0 as Depth
    FROM Employee e
    WHEREid = @SupervisorID 
    UNION All 
    SELECT e2.ID, e2.supervisorid, Depth + 1
    FROM Employee e2
        JOIN Family 
            On Family.id = e2.supervisorid 
) 
SELECT*
FROM Family 

更多信息:

Recursive Queries Using Common Table Expressions

答案 1 :(得分:0)

一些递归函数,它返回主管(如果有的话)或null。也可以是一个调用自身的SP,并使用UNION。

答案 2 :(得分:0)

您可能对物化路径"感兴趣解决方案,它稍微对表进行规范化,但可以在任何类型的SQL数据库上使用,并且可以防止您不必进行递归查询。实际上,它甚至可以在无SQL数据库上使用。

您只需要添加一个包含对象整个祖先的列。例如,下表包含一个名为tree_path的列:

+----+-----------+----------+----------+
| id | value     | parent   | tree_path|
+----+-----------+----------+----------+
|  1 | Some Text |        0 |          |
|  2 | Some Text |        0 |          |
|  3 | Some Text |        2 |       -2-|
|  4 | Some Text |        2 |       -2-|
|  5 | Some Text |        3 |     -2-3-|
|  6 | Some Text |        3 |     -2-3-|
|  7 | Some Text |        1 |       -1-|
+----+-----------+----------+----------+

选择id = 2的记录的所有后代如下所示:

SELECT * FROM comment_table WHERE tree_path LIKE '-2-%' ORDER BY tree_path ASC

要构建树,您可以按tree_path排序,以获得一个非常容易转换为树的数组。

您也可以索引tree_path,并且当通配符不在开头时可以使用索引。

例如,tree_path LIKE '-2-%'可以使用索引,但tree_path LIKE% - 2 - '`不能。

答案 3 :(得分:0)

SQL是用于执行 set 操作的语言,而递归不是其中的一种。此外,许多数据库系统在使用存储过程作为安全措施的递归上有一些限制,以防止流氓代码耗尽宝贵的服务器资源。

因此,在使用SQL时,请始终考虑'flat',而不是“ hierarchical”。因此,我强烈建议您使用已建议的'tree_path'方法。我使用了相同的方法,它非常出色而且非常关键,非常坚固。