递归与公用表表达式 - 何时使用CTE?

时间:2015-04-18 20:52:31

标签: sql recursion common-table-expression recursive-query

鉴于以下表格架构,我被问到如何找到Annie的所有下属。

-----------------------------
EmployeeId | Name | ManagerId
-----------------------------
1          | Annie| NULL
2          | Ben  | 1
3          | Carl | 2
4          | Den  | 1
....

来自ORM&服务器端背景,我写了一个递归函数来解决问题。但是,我被告知使用CTE有不同的方式。为什么以及何时使用CTE?为什么不递归? CTE比递归更快吗?

无论如何,这是我的递归实现:

public class Employee{
    int employeeId;
    string name;
    public List<Employee> managers {get;set};
    public List<Employee> subordinates {get;set};
}

//find direct & non-direct reports
public List<Employee> getSubordinates(Employee emp) {
    List<Employee> reports = new List<Employee>();
    if (emp.subordinates == null || emp.subordinates.Count == 0) 
       return null;

    foreach(Employee e in emp.subordinates) {
       reports.AddRange(getSubordinates(e));
    }

    return reports.DistinctBy(x=>x.employeeId);
}

1 个答案:

答案 0 :(得分:0)

公用表表达式(CTE)可以帮助你从数据库端accomplish recursion,所以实际上你将完成与你的方法相同的事情,关键的例外是它通过SQL完成一个查询,例如:

WITH subordinates AS (
    SELECT e.EmployeeId, e.Name
    FROM dbo.Employee e
    WHERE e.ManagerId = 1
    UNION ALL
    SELECT e.EmployeeId, e.Name
    FROM dbo.Employee e
        INNER JOIN subordinates s ON s.EmployeeId = e.ManagerId
)
SELECT s.EmployeeId, s.Name
FROM subordinates s;

好处是它可能更快,因为它是在一个查询中完成的,而不是从递归ORM方法生成的几个查询。

T-SQL Fiddle Example