2009-12-15 6 views
2

리프 노드의 올바른 수량 값만을 보장하는 BOM 구조의 수량을 다시 계산해야합니다.상향식 계층 구조에서 집계 된 값 계산

위의 내용이 약간 모호한 경우 걱정하지 마십시오. 아래는 간단한 예입니다.

ID (PK), PID (계층 구조의 상위 ID) 및 Q (현재 레코드의 수량 - 수량)의 세 가지 열을 정의하는 계층 적 테이블을 생각해보십시오.

set nocount on 
declare @results table(
     ID nvarchar(3), 
     PID nvarchar(3), 
     Q int, 
     lvl int, 
     ord int 
    ) 

ord 열은 결과를 정렬하는 용도로만 사용됩니다.

lvl 열은 계층 구조의 현재 레코드에 대한 수준을 정의합니다.

이러한 열을 유지하는 방법을 궁금해하는 분들을 위해 @results 테이블은 모든 트릭을 수행하는 함수로 실제 세계에 채워집니다. 이 예제의 경우 하드 코딩 된 값이 제공됩니다.

올바른 Q 값은 계층 구조의 리프 수준 노드에만 보장됩니다. 다른 노드들에 대해서는 Q가 정확하게 정의되지 않을 수도 있고 그렇지 않을 수도있다. 내 임무는 이들 노드에 대한 Q 값을 재 계산하는 것이다.

샘플 데이터 :

insert into @results(ord, lvl, ID, PID, Q) 
select 1, 0, 'A' as ID, null as PID, null as Q union 
select 2, 1, 'B' , 'A' , 15 union 
select 3, 1, 'C' , 'A' , 10 union 
select 4, 2, 'B1' , 'B' , 6 union 
select 5, 2, 'B2' , 'B' , 4 union 
select 6, 2, 'C1' , 'C' , 5 union 
select 7, 2, 'C2' , 'C' , 3 union 
select 8, 3, 'C11', 'C1', 4 union 
select 9, 3, 'C12', 'C1', 3 

당신이 볼 수있는 바와 같이, B 및 C1의 수량이 잘못이다 : 그들은 15와 5있어하지만 10 7 있어야한다 : 여기

select * from @results order by ord 

가 있어요 초기 데이터 :

ID PID   Q   lvl   ord 
---- ---- ----------- ----------- ----------- 
A NULL  NULL   0   1 
B A    15   1   2 
C A    10   1   3 
B1 B    6   2   4 
B2 B    4   2   5 
C1 C    5   2   6 
C2 C    3   2   7 
C11 C1    4   3   8 
C12 C1    3   3   9 

마지막 질문 : 가 세트 -이 테이블을 업데이트 할 수있는 방법이 따라서 모든 수량이 하위 노드의 상향식 합계 수량으로 업데이트됩니까?

내가 아래에 볼 수 있습니다와 함께 가장

있지만 기초 세트 아니에요 :

ID PID   Q   lvl   ord 
---- ---- ----------- ----------- ----------- 
A NULL   20   0   1 
B A    10   1   2 
C A    10   1   3 
B1 B    6   2   4 
B2 B    4   2   5 
C1 C    7   2   6 
C2 C    3   2   7 
C11 C1    4   3   8 
C12 C1    3   3   9 

감사합니다 : 정확한 양을 제공

declare @level int 

select @level = max(lvl) from @results 

while (@level > 0) 
begin 
    update r set Q = s.SumQ 
    from @results r inner join (
      select PID, sum(Q) as SumQ 
      from @results 
      where lvl = @level group by PID 
     ) s on (r.ID = s.PID) 

    set @level = @level - 1 
end 

select * from @results 

!

답변

2
;WITH q AS 
     (
     SELECT *, id AS initial 
     FROM @results 
     UNION ALL 
     SELECT r.*, initial 
     FROM q 
     JOIN @results r 
     ON  r.pid = q.id 
     ) 
UPDATE ru 
SET  q = qn.nq 
FROM @results ru 
JOIN (
     SELECT initial, 
       SUM(rq) AS nq 
     FROM q 
     LEFT JOIN 
       (
       SELECT id, 
         CASE 
         WHEN EXISTS 
         (
         SELECT NULL 
         FROM @results ri 
         WHERE ri.pid = r.id 
         ) 
         THEN NULL 
         ELSE q 
         END AS rq 
       FROM @results r 
       ) r 
     ON  r.id = q.id 
       AND r.id <> q.initial 
     GROUP BY 
       q.initial 
     ) qn 
ON  ru.id = qn.initial 
     AND qn.nq IS NOT NULL 
+0

+1 coz '작동하지만 그 동안 잠시 씹어 야합니다. :) –

관련 문제