Обновить запрос для обновления записей «между» другими записями? - PullRequest
1 голос
/ 10 марта 2012

Пример таблицы:

 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 и так далее.Они не могут вернуться и ссылаться на ProductY в строке 1.

Наборы данных не всегда одинаковы, и в наборе данных может быть больше элементов типа "Checker".

Когда есть только один, он работает очень хорошо, очевидно.Но когда их несколько, у меня возникают проблемы, когда общее количество продуктов неверно, потому что оно использует неправильное значение "Checker".

Ответы [ 3 ]

2 голосов
/ 10 марта 2012

Я думаю, что этот запрос работает.

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 из ряда CHECKER, который является самым высоким, но все еще ниже, чем рассматриваемая ИГРУШКА. Второй просто заменяет N шашки стоимостью чекера. Тогда у вас есть прямое слияние. Предполагая, что столбец N уникален, у вас никогда не будет нескольких совпадений.

1 голос
/ 11 марта 2012

Это должно сработать:

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', поэтому я оставил значение NULL.

0 голосов
/ 10 марта 2012

Я не вижу способа сделать это, как я предпочитаю - на основе набора.

Вы всегда можете прибегнуть к курсору - он не совсем высокопроизводительный или что-то в этом роде, но он работает,Если это всего лишь один раз, тогда ты в порядке.Если вам нужно делать это часто, вы можете продолжить поиск лучшего решения:

-- 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...