2015-01-09 97 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; 

希望這會有所幫助。