2012-09-11 4 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에 의해 아이들이 필요합니까 테이블 고객을 대체 할 @t를 사용? 필요한 데이터가 무엇인지 명확하게 작성하십시오. – levi

답변

0

입니다. 이 예는

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