2012-03-09 131 views
1

樣品表:更新查詢以更新'其他記錄之間的記錄?

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

回答

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」時,獲取每個玩具方格行是最高,同時仍然比所討論的TOY下的N。第二個是用檢查器的代價替換檢查器的N個。那麼你有一個直接的合併。假設N列是唯一的,你將永遠不會有多個匹配。

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

你沒有說總應該是什麼樣的「檢查」行,所以我把它NULL。