样本表:
N ProductName Cost Type TOTAL
1 ProductX 3 Checker
2 Product0 5 TOY
3 Product1 5 TOY
4 Product2 8 TOY
行2,3,4需要Type = Checker +当前行成本进入TOTAL列。因此第2行将是8,3将是8,而4将是11
5 ProductZ 10 Checker
6 Product3 5 TOY
7 Product4 9 TOY
8 Product5 18 TOY
9 Product6 25 TOY
同样,这些需要将ProductZ的成本添加到其总数中。因此第6行将是15,7将是19,依此类推。他们无法返回并在第1行引用ProductY。
数据集并不总是相同,并且数据集中可能有更多“Checker”类型的项目。
当只有一个时,显然效果很好。但是当有多个问题时,产品总数是错误的,因为它使用了错误的“Checker”值。
答案 0 :(得分:2)
我认为此查询有效。
WITH toysAndCheckers AS
(
SELECT n AS toy, (SELECT top 1 lowerCheckers.n From sampleTable AS lowerCheckers
WHERE lowerCheckers.N < theToys.N
AND lowerCheckers.[type] = 'Checker'
ORDER by n desc) AS matchingChecker
FROM sampleTable AS theToys
WHERE theToys.[type] = 'TOY'
),
toyCostAdjustments AS
(SELECT toy, cost AS checkerAdjustment
FROM toysAndCheckers
JOIN sampleTable
ON MatchingChecker = n
)
MERGE sampleTable
USING
toyCostAdjustments
ON n = toy
WHEN MATCHED THEN UPDATE
SET total = cost + CheckerAdjustment
;
第一个CTE,“toysAndCheckers”,为每个玩具获得最高的CHECKER行的N,同时仍低于所讨论的TOY。第二个只是用cheker的成本替换了检查器的N.然后你有一个简单的合并。假设N列是唯一的,您将永远不会有多个匹配。
答案 1 :(得分:1)
这应该有效:
with Numbered as (
select
(select top (1) Cost from T as T2
where T2.N <= T.N
and T2.Type = 'Checker'
order by N) as fv,
*
from T
)
update Numbered set
TOTAL = Cost + fv
where Type <> 'Checker';
你没有说'Checker'行的TOTAL应该是什么,所以我把它留给了NULL。
答案 2 :(得分:0)
我认为没有办法以我的首选方式做到这一点 - 以基于集合的方式。
你可以随时使用光标 - 它不是高性能或任何东西,但它可以工作。如果这只是一次性的,那你就没事了。如果您经常需要这样做,您可能希望继续寻找更好的解决方案:
-- declare a table variable for testing
DECLARE @sample TABLE (Num INT PRIMARY KEY, ProductName VARCHAR(50), Cost INT, ProdType VARCHAR(10), Total INT)
-- insert some data
INSERT INTO @sample VALUES
(1, 'ProductX', 3, 'Checker', NULL),
(2, 'Product0', 5, 'TOY', NULL),
(3, 'Product1', 5, 'TOY', NULL),
(4, 'Product2', 8, 'TOY', NULL),
(5, 'ProductZ', 10, 'Checker', NULL),
(6, 'Product3', 5, 'TOY', NULL),
(7, 'Product4', 9, 'TOY', NULL),
(8, 'Product5', 18, 'TOY', NULL),
(9, 'Product6', 25, 'TOY', NULL),
(10, 'ProductY', 15, 'Checker', NULL),
(11, 'Product7', 15, 'TOY', NULL),
(12, 'Product8', 12, 'TOY', NULL),
(13, 'Product9', 5, 'TOY', NULL)
-- declare the cursor, specify that we want to UDPATE the Total column
DECLARE SampleCursor CURSOR KEYSET FOR
SELECT Cost, Prodtype
FROM @sample
ORDER BY Num
FOR UPDATE OF Total
-- declare and initialize variables
DECLARE @Cost INT, @LastCheckerCost INT, @ProdType VARCHAR(10)
SET @LastCheckerCost = 0
-- open cursor and iterate over data set
OPEN SampleCursor
FETCH NEXT FROM SampleCursor INTO @Cost, @ProdType
-- while we have data......
WHILE @@FETCH_STATUS = 0
BEGIN
-- if we have a "Checker" row -> remember that value for later
IF @ProdType = 'Checker'
SET @LastCheckerCost = @Cost
ELSE
-- if we have a "normal" row, update the Total column
UPDATE @sample
SET Total = @LastCheckerCost + @Cost
WHERE CURRENT OF SampleCursor
-- get next set of data
FETCH NEXT FROM SampleCursor INTO @Cost, @ProdType
END
-- close and clean up cursor
CLOSE SampleCursor
DEALLOCATE SampleCursor
-- inspect results
SELECT * FROM @Sample