Sql 如何将此游标操作转换为闭包层次结构上基于集合的操作? Trees.DirectReports是一个闭包(层次结构)表 有一个名为Users的表,其中包含:RowID、EmployeeId和MangerId@RowCount是此表中的记录数,#EmpMgr是此表的光标

Sql 如何将此游标操作转换为闭包层次结构上基于集合的操作? Trees.DirectReports是一个闭包(层次结构)表 有一个名为Users的表,其中包含:RowID、EmployeeId和MangerId@RowCount是此表中的记录数,#EmpMgr是此表的光标,sql,sql-server-2012,hierarchy,hierarchical-data,transitive-closure-table,Sql,Sql Server 2012,Hierarchy,Hierarchical Data,Transitive Closure Table,下面是我想从基于游标的操作转换为基于集合的操作的相关sql代码 WHILE @RowCount <= @NumberRecords --loop through each record in Users table BEGIN SET @EmpId = (SELECT EmployeeId FROM #EmpMgr WHERE RowID = @RowCount) SET @MgrId = (SELECT ManagerId FROM #EmpMgr WHER

下面是我想从基于游标的操作转换为基于集合的操作的相关sql代码

WHILE @RowCount <= @NumberRecords --loop through each record in Users table
BEGIN       
    SET @EmpId = (SELECT EmployeeId FROM #EmpMgr WHERE RowID = @RowCount)
    SET @MgrId = (SELECT ManagerId FROM #EmpMgr WHERE RowID = @RowCount)

    INSERT INTO [Trees].[DirectReports](EmployeeId, ManagerId, Depth)
    SELECT c.EmployeeId, p.ManagerId, p.Depth + c.Depth + 1
    FROM Trees.DirectReports p join Trees.DirectReports c
    WHERE p.EmployeeId = @MgrId AND c.ManagerId = @EmpId

    SET @RowCount = @RowCount + 1
END

WHILE@RowCount在其他几个帖子的帮助下找到了我想要的东西。主要答案是:

WITH cte AS
(
    SELECT LegacyId ancestor, LegacyId descendant, 0 depth FROM Users
    UNION ALL

    SELECT cte.ancestor, u.LegacyId descendant, cte.depth + 1 depth
    FROM   dbo.Users u JOIN cte ON u.ManagerId = cte.descendant
)
select * from cte
然而,一开始让我感到不快的是,有一些坏数据导致了循环依赖。我能够使用以下查询来确定这些实例的位置:

with cte (id,pid,list,is_cycle) 
as
(
    select      legacyid id, managerid pid,',' + cast (legacyid as varchar(max))  + ',',0
    from        users

    union all

    select      u.legacyid id, 
                u.managerid pid, 
                cte.list + cast(u.legacyid as varchar(10)) +  ',' ,case when cte.list like '%,' + cast (u.legacyid as varchar(10)) + ',%' then 1 else 0 end
    from        cte join users u on u.managerid = cte.id
    where       cte.is_cycle = 0
)
select      *
from        cte
where       is_cycle = 1

一旦我修正了周期性数据,一切都很顺利。查看以下SO帖子以了解更多信息,因为这些是我过去提出的解决方案:

在其他几篇帖子的帮助下找到了我想要的。主要答案是:

WITH cte AS
(
    SELECT LegacyId ancestor, LegacyId descendant, 0 depth FROM Users
    UNION ALL

    SELECT cte.ancestor, u.LegacyId descendant, cte.depth + 1 depth
    FROM   dbo.Users u JOIN cte ON u.ManagerId = cte.descendant
)
select * from cte
然而,一开始让我感到不快的是,有一些坏数据导致了循环依赖。我能够使用以下查询来确定这些实例的位置:

with cte (id,pid,list,is_cycle) 
as
(
    select      legacyid id, managerid pid,',' + cast (legacyid as varchar(max))  + ',',0
    from        users

    union all

    select      u.legacyid id, 
                u.managerid pid, 
                cte.list + cast(u.legacyid as varchar(10)) +  ',' ,case when cte.list like '%,' + cast (u.legacyid as varchar(10)) + ',%' then 1 else 0 end
    from        cte join users u on u.managerid = cte.id
    where       cte.is_cycle = 0
)
select      *
from        cte
where       is_cycle = 1
一旦我修正了周期性数据,一切都很顺利。查看下面的SO帖子,了解更多信息,因为这些都是我以前提出的解决方案:和