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

Sql 更新查询以更新其他记录之间的记录?,sql,sql-server-2008,Sql,Sql Server 2008,样本表: N ProductName Cost Type TOTAL 1 ProductX 3 Checker 2 Product0 5 TOY 3 Product1 5 TOY 4 Product2 8 TOY 第2、3

样本表:

 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
同样,这些需要将产品成本z加到它们的总数中。第6行是15行,第7行是19行,依此类推。他们无法返回并引用第1行的ProductY

数据集并不总是相同的,数据集中可能有更多的棋盘格类型的项


当只有一个的时候,很明显,它工作得很好。但是,当出现多个问题时,我会发现产品总数是错误的,因为它使用了错误的检查值。

我看不到任何方法来实现这一点,这是我首选的方法-以集合为基础的方式

你可以随时使用光标——它不是高性能的,也不是任何东西,但它可以工作。如果那只是一次性的,那你就没事了。如果您需要经常这样做,您可能希望继续寻找更好的解决方案:

-- 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 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,为每个玩具获取棋盘格行中最高的N,同时仍然低于所讨论的玩具。第二种方法只是用cheker成本替换checker的N。然后你有一个简单的合并。假设N列是唯一的,您将永远不会有多个匹配项。

这应该可以:

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”行的总计应该是多少,因此我将其保留为空。

不幸的是,由于前端限制,我无法在t-SQL中执行此操作。。因此,如果无法通过某种查询遍历行,我将不得不重新考虑这一点。为什么不添加一个列检查器Id,它引用作为“主”产品的产品Id。或者,如果有多个检查器,则为多对多表。将此描述为对于类型中包含玩具的任何给定行,可能有一些行在第N列中的值较低,并且在类型中包含值检查器,这是否正确。如果有任何带有棋盘格的行,它们在N中都有不同的值。最高的一行是玩具附带的棋盘格?也就是说,你总是对比任何给定的玩具都少N的最高N棋盘格感兴趣?对于2008年可用的合并查询来说,这可能很容易做到,请确认,有人会为您编写它。如果不让我知道我怎么没抓住要点。n是自动编号。玩具的n值始终高于需要用于计算的棋盘格。