2015-01-09 98 views
2

我有一个表结构如下SQL递归CTE - 请参考亲

userId  userName   managerId 
----------- ---------------- ----------- 
1   John    NULL 
2   Charles   1 
3   Nicolas   NULL 
4   Neil    3 

而且我有具有以下

userId  shareId   
----------- ----------- 
1   1001    
3   1002    

所以我下面的查询到另一个表让我的递归CTE:

WITH UserCTE AS (
    SELECT userId, userName, managerId,0 AS steps 
    FROM dbo.Users 
    WHERE userId = 7 

    UNION ALL 

    SELECT mgr.userId, mgr.userName, mgr.managerId, usr.steps +1 AS steps 
    FROM UserCTE AS usr 
    INNER JOIN dbo.Users AS mgr 
     ON usr.managerId = mgr.userId 
) 
SELECT * FROM UserCTE AS u;   

将会产生以下结果

userId  userName   managerId steps  
----------- ---------------- ----------- ----------- 
1   John    NULL  0   
2   Charles   1   1   
3   Nicolas   NULL  0   
4   Neil    3   1  

好吧,我想知道的是shareId为拥有它的用户,也为属于他们的用户。

预期结果

userId  userName   managerId steps  shareId 
----------- ---------------- ----------- ----------- ---------- 
1   John    NULL  0   1001 
2   Charles   1   1   1001 
3   Nicolas   NULL  0   1002 
4   Neil    3   1   1002 

有什么办法实现呢?

感谢

回答

3

加入Share table用的Recursive CTE锚查询Users表。尝试这个。

;WITH UserCTE 
    AS (SELECT c.userId, 
       userName, 
       managerId, 
       0 AS steps, 
       shareId 
     FROM dbo.Users c 
       LEFT JOIN share_table s 
        ON c.userId = s.userId 
     WHERE managerId IS NULL 
     UNION ALL 
     SELECT mgr.userId, 
       mgr.userName, 
       mgr.managerId, 
       usr.steps + 1 AS steps, 
       usr.shareId 
     FROM UserCTE AS usr 
       INNER JOIN dbo.Users AS mgr 
         ON usr.userId = mgr.managerId) 
SELECT * 
FROM UserCTE AS u 
ORDER BY userId; 
+0

非常感谢,这正是我所期待的。 – user3362714 2015-01-10 19:32:59

1

你可以在cte表和用户共享表上做left join

WITH UserCTE AS (
    SELECT userId, userName, managerId,0 AS steps 
    FROM dbo.Users 
    where managerId IS NULL 

    UNION ALL 

    SELECT mgr.userId, mgr.userName, mgr.managerId, usr.steps +1 AS steps 
    FROM UserCTE AS usr 
    INNER JOIN dbo.Users AS mgr 
    ON usr.userId = mgr.managerId 
) 
SELECT * FROM UserCTE AS u 
left join userShare us 
on u.managerId = us.userId 
or u.userId = us.userId 
order by u.userId 
1

一种方法是使用在UserCTE表和share表之间的连接的OR。例如:

WITH UserCTE AS (
    SELECT userId, userName, managerId,0 AS steps 
    FROM dbo.Users 
    WHERE userId = 7 

    UNION ALL 

    SELECT mgr.userId, mgr.userName, mgr.managerId, usr.steps +1 AS steps 
    FROM UserCTE AS usr 
    INNER JOIN dbo.Users AS mgr 
     ON usr.managerId = mgr.userId 
) 
SELECT * FROM UserCTE AS u 
INNER JOIN [share table] AS s 
    ON u.userId = s.userId OR u.managerId s.userId; 

然而,这是否有大于一个水平等级管理制度有程序重复的可能性。即经理也有经理。另一种方法是在UserCTE表的UserCTE表的表中将userId列中的一个加到share表上,将另一个managerId表的UserCTE表中的两个加到share表中。然后,您可以在shareId列上使用CASE声明来决定您需要哪一个。见下:

WITH UserCTE AS (
    SELECT userId, userName, managerId,0 AS steps 
    FROM dbo.Users 
    WHERE userId = 7 

    UNION ALL 

    SELECT mgr.userId, mgr.userName, mgr.managerId, usr.steps +1 AS steps 
    FROM UserCTE AS usr 
    INNER JOIN dbo.Users AS mgr 
     ON usr.managerId = mgr.userId 
) 
SELECT 
    u.* 
    ,CASE 
     WHEN su.shareId is not null THEN su.shareId 
     WHEN sm.shareId is not null THEN sm.shareId 
     ELSE null END as shareID 
FROM UserCTE AS u 
LEFT JOIN [share table] AS su 
    ON u.userId = s.userId 
LEFT JOIN [share table] AS sm 
    ON u.managerId = s.userId; 

希望这会有所帮助。