2013-10-14 156 views
0

我有一大組數據需要根據價格進行更新。非常簡單,代碼/尺寸1中物品的價格必須等於或小於代碼/尺寸2.代碼/尺寸2必須等於或小於代碼/尺寸3,依此類推:根據列值更新SQL表

Item  Code Size Price 
------------------------------- 
66227019 OTH  1 $466 
66227019 OTH  2 $486 
66227019 OTH  3 $476 
66227019 OTH  4 $537 

66227019 IVC  1 $458 
66227019 IVC  2 $428 
66227019 IVC  3 $458 
66227019 IVC  4 $458 

必須像:

Item  Code Size Price 
------------------------------- 
66227019 OTH  1 $466 
66227019 OTH  2 $486 
66227019 OTH  3 $486 
66227019 OTH  4 $537 

66227019 IVC  1 $458 
66227019 IVC  2 $458 
66227019 IVC  3 $458 
66227019 IVC  4 $458 

我已經嘗試了一些自聯接和我基本上失去了我的腦海裏。任何幫助真誠讚賞。

謝謝!

+1

SQL-Server或其他DBMS?版? –

+0

也許我會失明,但你期望的結果有什麼不同? – Andrew

+0

如果有另一條記錄具有相同的商品和代碼,而較低的尺寸和更高的價格,您是否希望提高{商品,代碼,尺寸}條目的價格? – 2013-10-14 21:57:09

回答

3

對於SQL-Server 2012中,您可以使用此:

; WITH cte AS 
(SELECT *, 
     MaxPrice = MAX(Price) 
        OVER (PARTITION BY Item, Code 
          ORDER BY Size 
          ROWS BETWEEN UNBOUNDED PRECEDING 
            AND 1 PRECEDING 
         ) 
    FROM Products 
) 
UPDATE cte 
SET Price = MaxPrice 
WHERE Price < MaxPrice ; 

測試在SQL-Fiddle

+0

這個伎倆!再次感謝,我將不得不查看之間的行無邊界前衛和1前衛。從來沒有見過一個之前。乾杯! –

1

這是否得到你所需要的?

UPDATE LaterRec 
SET Price = PrevRec.Price 
FROM Data AS LaterRec 
    INNER JOIN Data AS PrevRec ON LaterRec.Item = PrevRec.Item AND LaterRec.Code = PrevRec.Code AND PrevRec.Size < LaterRec.Size 
WHERE 
     PrevRec.Price > LaterRec.Price 
    -- Disregard this entry if there's a record *between* PrevRec and LaterRec 
    AND NOT EXISTS (SELECT * FROM Data AS Intrmdt WHERE LaterRec.Item = Intrmdt.Item AND LaterRec.Code = Intrmdt.Code AND Intrmdt.Size > PrevRec.Size AND Intrmdt.Size < LaterRec.Size) 
1

答案是遞歸的CTE。不依賴於SQL SERVER版本。

DECLARE @t TABLE 
    (
     item  INT 
     ,code  sysname 
     ,SIZE  INT 
     ,price  INT 
    ) 
    INSERT INTO @t(item, code, SIZE, price) 
       SELECT 1,'oth',1,466 
    UNION ALL SELECT 1,'oth',2,486 
    UNION ALL SELECT 1,'oth',3,476 
    UNION ALL SELECT 1,'oth',4,537 

    UNION ALL SELECT 1,'ivc',1,458 
    UNION ALL SELECT 1,'ivc',2,428 
    UNION ALL SELECT 1,'ivc',3,458 
    UNION ALL SELECT 1,'ivc',4,458 

    SELECT * FROM @t 

    ;WITH cte1 (item,code,size,price,rownum1,rownum2) 
    AS 
    (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY item,code ORDER BY item,code,SIZE) AS rownum1, ROW_NUMBER() OVER (ORDER BY item,code,SIZE) AS rownum2 
     FROM @t 
    ), 
    cte2 (item,code,size,price,rownum1,rownum2) 
    AS 
    (
     SELECT * 
     FROM cte1 t1 
     WHERE rownum2=1 

     UNION ALL 

     SELECT t1.item,t1.code,t1.size 
       ,CASE WHEN t1.price>=t2.price THEN t1.price 
         WHEN t1.price<t2.price THEN t2.price 
       END AS proce 
       ,t1.rownum1,t1.rownum2 
     FROM cte2 t2 
     JOIN cte1 t1 
      ON t2.rownum2+1=t1.rownum2 
    ) 
    SELECT item,code,size,price FROM cte2 

enter image description here

+2

遞歸CTE可能非常昂貴 - 因爲OP在SQL Server 2012上,所以我傾向於使用更高效的解決方案。 –

+1

好吧,如果沒有正確實施並且獲取不必要的數據,它是很昂貴的。但是,OP是用於SQL 2012的,因此可以使用新功能,具體取決於其性能。儘管如此,我還沒有比較過。 –

0

假設t是你的表的名稱:

update t set price=p 
from (
    select nxt.item i,nxt.code c,nxt.size s,max(cur.price) p 
    from t cur join t nxt 
    on (cur.item=nxt.item and cur.code=nxt.code 
    and cur.size<nxt.size and cur.price>nxt.price) 
    group by nxt.item,nxt.code,nxt.size  
) a 
where item=i and code=c and size=s 
+0

如果同一個項目和代碼有多個記錄具有較低的大小,則此查詢是否會返回多個記錄,因此無法更新? – 2013-10-14 22:39:48

+0

@JonofAllTrades:你的意思是,例如,如果第四個價格改變爲477? – geomagas

+1

但是'cur'加入到每個記錄中的一個較小的大小,每次都是'nxt'。我沒有看到你刪除重複的地方。例如,如果{OTH,4}爲$ 0,表格將自我加入4到3,並且也是4到2,並且4到1. – 2013-10-14 23:01:01