2012-09-11 5 views
1

나는이 구조와 테이블이 :계층 합

Id ParentId CountItems 

내가 스크립트 항목에 대한 수준을 CALC 수 있습니다 내가 가기 낮은 수준에서 상승 할

;WITH cteSort AS 
    (
    SELECT Id AS Child, ParentId AS Parent, 1 AS [Level] 
    FROM [Catalog].[Category] WHERE Id = 0 
    union ALL 
    SELECT Id AS Child, ParentId AS Parent, [Level] + 1 AS [Level] 
    FROM [Catalog].[Category] 
     INNER JOIN cteSort ON [Category].ParentId = cteSort.Child and Id <>0) 

을 현재에 넣어 CountItems 하위 레벨의 CountItems 하위 필드와 현재 CountItems의 합계를 나타냅니다. 이처럼 : 내가 최근 관계형 프리젠 테이션에서 나무에 문제가 있었다

Id ParentId count 
0  0  0 
1  0  1 
2  0  1 
3  1  1 
4  1  1 
5  2  1 
6  3  1 
7  4  1 
8  4  1 

Id ParentId count 
0 0  8 
1 0  6 
2 0  2 
3 1  2 
4 1  3 
5 2  1 
6 3  1 
7 4  1 
8 4  1 

답변

1

후, 그래서 내가 당신의 문제를 해결하려고하기 전에 그러나 나는 다음과 같은 출력을 얻을 몇 가지 시도 후 : GROUP BY, HAVING, or aggregate functions are not allowed in the recursive part of a recursive common table expression 다음 글을 쓸 때

나는이 문제를 해결하는 것이 불가능하다고 생각합니다. i CTE. 그래서 모든 아이들의 총 수를 제공하는 재귀 함수를 작성합니다. 이 당신의 작업과

CREATE FUNCTION [dbo].[GetSumOfChildren](@CategoryId INT) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @sum int; 
    SELECT 
     -- get sum of all children 
     @sum = SUM(dbo.GetSumOfChildren(Id)) 
    FROM 
     Category 
    WHERE ParentId = @CategoryId AND ParentId <> Id 

    SELECT 
     -- plus self count 
     @sum = ISNULL(@sum,0) + [Count] 
    FROM 
     Category 
    WHERE Id = @CategoryId 

    RETURN @sum; 
END 

내가 당신의 질문은 왜 더 많은 리드 추측

SELECT Id,ParentId, dbo.GetSumOfChildren(Id) FROM Category 
0

간단한 해결? 실제 해결책 (내 점심 시간에이 문제에 의아해하면서)보다는 약간의 기여를해야합니다.

순수 프로그래밍 용어로, 현재 리프의 내부 카운트를 유지하면서 부모 카운트와 노드를 통과하는 재귀 함수를 사용하여이를 수행 할 수 있습니다. 순수한 SQL로이를 에뮬레이션하는 것은 사용되는 프로그래밍 기술의 일부가 SQL에 구현하는 것이 훨씬 어렵 기 때문에보다 흥미로운 시도가 될 것입니다.

내 생각으로는 행 당 개수가 많은 서브 행을 사용하지 않았지만 (결과적으로 행 수가 많고 고정 된 수의 수준이 필요할 수 있음) 결과 집합을 XML 개체로 변환하고 그런 다음 XQuery를 사용하여 자손 수를 얻은 다음 결과로 결과 세트를 갱신하십시오. 불행히도 count()에는 모든 자손을 카운트하는 스위치가 없으므로 행 단위로 카운트하려면 하위 쿼리 유형 논리로 되돌려 야합니다. 또한이 방법은 고정 된 수의 레벨을 갖는 것을 가리키는 것 같습니다.

그 이유는 무엇입니까? 이 결과 집합을 C#, Java 등의 프로그래밍 언어로 전달하면 그 시점에서 재귀 계산을 구현하고이를 소비하기 전에 결과 집합에 추가하는 것이 훨씬 더 중요합니다. 삽입 새로운 분야에 테이블 [수준]을

+0

나는 solutuion 찾을 : – handmade

1

내 자신의 솔루션 :

;WITH cteSort AS 
    (
    SELECT Id AS Child, ParentId AS Parent,1 AS [Level] 
    FROM table WHERE Id = 0 
    union ALL 
    SELECT 
    Id AS Child, 
    ParentId AS Parent, 
    cteSort.[Level] + 1 AS [Level] 
    FROM table 
     INNER JOIN cteSort ON table.ParentId = cteSort.Child and table.Id<>0) 

UPDATE table SET [Level] = (Select [Level] from cteSort where cteSort.Child = table.Id) 

declare @max int 
set @max = (select top(1) [Level] from table order by [Level] Desc) 
while (@max >0) 
begin 
    UPDATE t1 
     SET t1.[count] = t1.[count] + t2.cnt , 
     from table as t1 
     cross apply (Select COALESCE(SUM([count]),0) cnt from table where ParentId =t1.Id) t2 
     where t1.Id in (Select Id from table where [Level] [email protected]) 
    Set @max = @max -1 
end 
+0

그것은 작업의 좋은,하지만 난 "크로스 적용"무거운 것을들을 수 – handmade