2012-09-11 229 views
0

我有點混亂的數據集,我需要爲特定的父帳戶獲取所有子帳戶。遞歸SQL查詢

的表如下

代碼(PK),名稱,ParentCode

沒有外鍵

從我可以看到,如果一個帳戶沒有ParentCode是一個空字符串,或者它被設置爲與代碼相同。

我一直在嘗試關注http://msdn.microsoft.com/en-us/library/ms186243(v=sql.105).aspx,但它似乎要返回所有數據,再加上我無法弄清楚如何才能讓孩子只用一個帳戶。

WITH DirectReports (ParentCus, Code, Name, Level) 
AS 
(
    SELECT ParentCode, Code, Name, 0 AS Level 
    FROM Customers 
     WHERE Code = ParentCode OR Code = '' 
    UNION ALL 

    SELECT c.ParentCode, c.Code, c.Name, level + 1 
    FROM Customers AS C 
    INNER JOIN DirectReports AS d 
     ON c.ParentCode = d.Code 
     where c.Code != d.Code 
) 
SELECT ParentCus, Code, Name, Level 
FROM DirectReports 

編輯 要清楚我需要能夠通過我的功能的代碼,並返回所有(遞歸),該賬戶子帳戶。

終極密碼 我不得不做出的答案稍有變化,但這裏是最後的工作代碼

declare @t table(code varchar(10), name varchar(10), parentcode varchar(10)) 
insert @t values(1, 'navn1', '1') 
insert @t values(2, 'navn2', '') 
insert @t values(3, 'navn3', 1) 
insert @t values(4, 'navn4', 3) 
insert @t values(5, 'navn5',4) 
insert @t values(6, 'navn6', 2) 
insert @t values(7, 'navn7', 3) 

declare @code varchar(10) -- or however code/parentcode is declared 
set @code = '1'   -- the parentcode you are trying to isolate 

;WITH DirectReports (ParentCus, Code, Name, Level) 
AS 
(
    SELECT ParentCode, Code, Name, 0 AS Level 
    FROM @t Customers 
    -- this picks the chosen code 
     WHERE Code = @code and (Code = ParentCode OR PARENTCode = '') 
    UNION ALL 
    SELECT c.ParentCode, c.Code, c.Name, level + 1 
    FROM 
     (select * from @t where code != parentcode) --had to do this to account for an infinate loop 
     as C 
    INNER JOIN DirectReports AS d 
     ON c.ParentCode = d.Code 

) 
SELECT ParentCus, Code, Name, Level 
FROM DirectReports 
-- level > 0: to ensure child accounts only 
where level > 0 
+0

你需要孩子通過parentId的?清楚地寫下你需要的數據 – levi

回答

0

你需要指定你想要的代碼。 這個例子是使用@t來代替你的表的客戶

declare @t table(code varchar(10), name varchar(10), parentcode varchar(10)) 
insert @t values(1, 'navn1', '') 
insert @t values(2, 'navn2', '') 
insert @t values(3, 'navn3', 1) 

declare @code varchar(10) -- or however code/parentcode is declared 
set @code = '1'   -- the parentcode you are trying to isolate 

;WITH DirectReports (ParentCus, Code, Name, Level) 
AS 
(
    SELECT ParentCode, Code, Name, 0 AS Level 
    FROM @t Customers 
    -- this picks the chosen code 
     WHERE Code = @code and (Code = ParentCode OR PARENTCode = '') 
    UNION ALL 
    SELECT c.ParentCode, c.Code, c.Name, level + 1 
    FROM @t C 
    INNER JOIN DirectReports AS d 
     ON c.ParentCode = d.Code 
    -- added to prevent infinite loop, 
    -- I should point out that when this happens, you have bad data in your base 
    WHERE c.ParentCode <> c.Code 
) 
SELECT ParentCus, Code, Name, Level 
FROM DirectReports 
-- level > 0: to ensure child accounts only 
-- level < 100:to prevent infinite loops caused by circular references 
where level > 0 and level < 100 
+0

只需稍作改動(見編輯),但是這樣做了。謝謝! – TheRealTy

+0

@tyrongower聽起來像你有不好的數據,我寫了另一種方式讓你避免這種情況。 –

0
;With CTE as 
(
select ParentCode, Code, Name,row_number() over (order by (select 0)) as rn from Customers 
) 

,DirectReports as (ParentCus, Code, Name, Level) 
AS 
(
    SELECT rn,ParentCode, Code, Name, 0 AS Level 
    FROM CTE WHERE rn=1 and (Code = ParentCode OR Code = '') 
    UNION ALL 

    SELECT c.ParentCode, c.Code, c.Name, level + 1 
    FROM CTE AS C 
    INNER JOIN DirectReports AS d 
     ON c.ParentCode = d.Code and c.rn=d.rn+1 
     where c.Code != d.Code 
) 
SELECT ParentCus, Code, Name, Level 
FROM DirectReports