更新查询以更新'其他记录之间的记录?

问题描述:

样品表:更新查询以更新'其他记录之间的记录?

N ProductName   Cost   Type   TOTAL 

1 ProductX    3    Checker 
2 Product0    5    TOY 
3 Product1    5    TOY 
4 Product2    8    TOY 

行2,3,4需要经济型=检查+当前行成本计入总列。因此,第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

不幸的是,我不能在给定前端限制的情况下在T-SQL中这样做。因此,如果无法通过某种查询遍历行,我将不得不重新考虑这一点。 – Mindflux 2012-03-09 21:54:49

+0

为什么不添加一个Checker_Id列,它对Product_Id作为'主'产品的引用。或者如果多于一个棋子,则是多桌多桌。 – rfcdejong 2012-03-09 22:07:55

+1

将此描述为“对于TYPE中的任何具有”玩具“的给定行,可能有一些行在列N中具有较低值并且在类型中具有值”CHECKER“。如果有任何行用Checker,它们在N中会有不同的值。最高的是与“TOY”一起使用的“Checker”?也就是说,你总是对“最高”(N)“Checker”感兴趣比任何给定的“玩具”更少(N)?这可能很容易做一个MERGE查询,在2008年可用,确认并且有人会为你写。如果不让我知道我是如何错过了这一点的。 – 2012-03-09 22:35:55

我觉得这个查询工作。

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”时,获取每个玩具方格行是最高,同时仍然比所讨论的TOY下的N。第二个是用检查器的代价替换检查器的N个。那么你有一个直接的合并。假设N列是唯一的,你将永远不会有多个匹配。

我没有看到任何方式做到这一点我的首选方式 - 以基于集合的方式。

你总是可以诉诸于游标 - 它不完全是高性能或任何东西,但它的工作原理。如果这只是一次性的,那么你很好。如果你需要经常这样做,你可能想继续寻找更好的解决方案:

-- 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 

这应该工作:

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'; 

你没有说总应该是什么样的“检查”行,所以我把它NULL。