我需要在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
最后,问题:有没有办法以基于集合的方式更新此表,以便使用自下而上的总计儿童节点数量更新所有数量?
我带来的最好的可以在下面看到,但它没有基于:
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
给出正确的数量:
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
谢谢!
答案 0 :(得分: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