如何设计SQL递归查询?

时间:2011-12-12 15:04:39

标签: tsql sql-server-2008

我如何重新设计下面的查询,以便它递归遍历整个树以返回从root到leaves的所有后代? (我正在使用SSMS 2008)。我们有一位总统。在他之下是副总裁,然后是高层管理人员等。我需要返回每个的名称和标题。但是这个查询不应该是硬编码的;我需要能够为任何选定的员工运行此项服务,而不仅仅是总裁。下面的查询是硬编码方法。

select P.staff_name [Level1], 
P.job_title [Level1 Title], 
Q.license_number [License 1],
E.staff_name [Level2], 
E.job_title [Level2 Title], 
G.staff_name [Level3], 
G.job_title [Level3 Title]

from staff_view A 
left join staff_site_link_expanded_view P on P.people_id = A.people_id
left join staff_site_link_expanded_view E on E.people_id = C.people_id
left join staff_site_link_expanded_view G on G.people_id = F.people_id
left join facility_view Q on Q.group_profile_id = P.group_profile_id

谢谢,这与我需要的最匹配。以下是我的CTE查询:

with Employee_Hierarchy (staff_name, job_title, id_number, billing_staff_credentials_code, site_name, group_profile_id, license_number, region_description, people_id)
as
(
    select C.staff_name, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
    from staff_view A
    left join staff_site_link_expanded_view C on C.people_id = A.people_id
    left join facility_view Q on Q.group_profile_id = C.group_profile_id
    left join regions R on R.regions_id = Q.regions_id
    where A.last_name = 'kromer'
)
select  C.staff_name, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
from staff_view A
left join staff_site_link_expanded_view C on C.people_id = A.people_id
left join facility_view Q on Q.group_profile_id = C.group_profile_id
left join regions R on R.regions_id = Q.regions_id
WHERE C.STAFF_NAME IS NOT NULL
GROUP BY C.STAFF_NAME, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
ORDER BY C.STAFF_NAME

但我想知道“Employee_Hierarchy”的目的是什么?当我用“Employee_Hierarchy”替换外部查询中的“staff_view”时,它只返回一条记录=“Kromer”。那么我们何时/何地可以使用“Employee_Hierarchy”?

1 个答案:

答案 0 :(得分:3)

请参阅:

<强>更新

正确的递归CTE基本上由三件事组成:

  • SELECT开头;可以选择例如根级员工(Reports_To为NULL),或者可以选择您定义的任意员工,例如通过参数

  • UNION ALL

  • 递归 SELECT语句,该语句从相同的,通常为自引用的表中进行选择,并与当前构建的递归CTE连接

这使您能够递归地构建一个结果集,然后可以从中选择。

如果查看Northwind示例数据库,它会有一个名为Employees的表格,该表格是自引用的:Employees.ReportsTo --> Employees.EmployeeID定义了谁向谁报告。

您的CTE看起来像这样:

;WITH RecursiveCTE AS
(
    -- anchor query; get the CEO
    SELECT EmployeeID, FirstName, LastName, Title, 1 AS 'Level', ReportsTo
    FROM dbo.Employees
    WHERE ReportsTo IS NULL

    UNION ALL

    -- recursive part; select next Employees that have ReportsTo -> cte.EmployeeID      
    SELECT 
       e.EmployeeID, e.FirstName, e.LastName, e.Title, 
       cte.Level + 1 AS 'Level', e.ReportsTo
    FROM 
       dbo.Employees e
    INNER JOIN 
       RecursiveCTE cte ON e.ReportsTo = cte.EmployeeID
)
SELECT *
FROM RecursiveCTE
ORDER BY Level, LastName    

我不知道你是否可以将你的样本翻译成适当的递归CTE - 但这基本上是它的要点:锚点查询,UNION ALL,递归查询