【问题标题】:Recursion vs Common Table Expression - when to use CTE?递归与公用表表达式 - 何时使用 CTE?
【发布时间】:2015-04-18 20:52:31
【问题描述】:

给定下表架构,有人问我如何找到 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);
}

【问题讨论】:

  • 使用CTE,您可以在服务器端实现递归,从而通过单个查询返回所需的结果集。你可以在这里找到很多如何做到这一点的例子。

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


【解决方案1】:

公用表表达式 (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

【讨论】:

    猜你喜欢
    • 2011-06-12
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-15
    • 2023-02-09
    • 1970-01-01
    相关资源
    最近更新 更多