2013-10-14 7 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-сервер или другой СУБД? Версия? –

+0

Может быть, я ослеп, но что по-вашему? – Andrew

+0

Вы хотите увеличить цену за элемент {Item, Code, Size}, если есть другая запись с тем же Item и Code и более низким размером с более высокой ценой? –

ответ

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

это сделало трюк! Еще раз спасибо, и мне придется искать ROWS МЕЖДУ НЕОГРАНИЧЕННЫМ ПРЕЦЕДЕНТОМ И 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

Если есть несколько записей для одного и того же элемента и кода с более низким размером, не будет ли этот запрос возвращать несколько записей и, следовательно, не сможет обновиться? –

+0

@JonofAllTrades: Вы имеете в виду, например, если 4-я цена была изменена, скажем, на 477? – geomagas

+1

Но 'cur' присоединяется к каждой записи с более низким размером, каждый раз как' nxt'. Я не вижу, где вы удаляете дубликаты. Например, если {OTH, 4} равнялся $ 0, таблица могла бы присоединяться с 4 до 3, а также от 4 до 2 и от 4 до 1. –

Смежные вопросы