2012-06-18 2 views
0

У меня есть база данных, которая, simiplified, заключается в следующем:Обновление столбца с самой ранней датой, которая имеет тот же идентификатор, и имеет столбец> 0

ID | SecondID | DateRecorded | NumberToCheck | NumberToUpdate 

NumberToUpdate в настоящее время имеет значение 0 для всех строк.

Я хочу, чтобы обновить NumberToUpdate со значением для NumberToCheck на той же строке, МИНУС значение для NumberToCheck, который имеет самый ранний DateRecorded «(Min(DateRecorded)», где NumberToCheck больше 0, и который имеет тот же идентификатор и secondID как оригинал ряд.

До сих пор я

UPDATE dbo.Table 
SET NumberToUpdate =//Update NumberToUpdate 
    NumberToCheck - //NumberToCheck from the current row, subtracting... 
     (SELECT TOP 1 t2.NumberToCheck FROM Table t2 WHERE ID = t2.ID AND secondID = t2.secondID AND t2.DateRecorded = 
     (SELECT TOP 1 MIN(t3.DateRecorded) FROM Table t3 WHERE t2.ID = t3.ID AND t2.secondID = t3.secondID AND t3.Passes > 0)) 
     //the NumberToCheck with the earliest date, of the same ID. 

Это не правильно, однако, и возвращает меня значения, которые не имеют смысла (в том числе значений минус которого не должно быть никакого!)

Что есть Я забыл здесь?

Большое спасибо

+0

1-я догадка: если вы берете первый NumbertoCheck, который отличен от нуля и отбрасывает его из некоторых ранних строк, имеющих нулевое значение, вы, вероятно, получите некоторые отрицательные числа. Возможно, вы не захотите их обновлять. – Bill

+0

Нет, не было бы отрицательных значений, поскольку число является кумулятивным :) –

+0

Обновление: теперь я добавил еще один столбец к моему примеру, что усложняет его. Мне нужно сопоставить как ID, так и SecondID в моем обновлении. До сих пор ни один из ответов не работал правильно для меня. –

ответ

1

Во-первых, вы должны начать с выбора запроса, чтобы получить значение, которое вы хотите:

select t.* 
from (select t.*, row_number() over (partition by id order by date) as seqnum 
     from table t 
     where number_to_check > 0 
    ) t 
where seqnum = 1 

Теперь вы можете использовать это в своем первоначальном обновление:

with vals as (select t.* 
       from (select t.*, row_number() over (partition by id order by date) as seqnum 
        from table t 
        where NumberToCheck > 0 
        ) t 
       where seqnum = 1 
      ) 
update table 
    set NumberToUpdate = NumberToCheck - vals.NumberToCheck 
from vals 
where t.id = vals.id 
+0

Это возвращает недопустимое имя объекта t при замене соответствующими данными моей базы данных. Я также сейчас немного изменил этот вопрос. –

+1

Я использовал имя «t» вместо «table». Тем не менее, обозначение таблицы «таблица» - плохая идея. Во-первых, «таблица» - это зарезервированное слово в SQL, и вы хотите избежать использования зарезервированных слов для имен таблиц и столбцов. Во-вторых, вы сможете найти менее общее название, чем таблица. –

0
UPDATE dbo.Table as t1 
INNER JOIN 
(
    SELECT MIN(DateRecord) as mindate, ID 
    FROM dbo.Table 
    GROUP BY ID 
) as mindates 
ON t1.ID = mindates.ID 
INNER JOIN 
dbo.Table as substractions 
ON mindates.mindate = substraction.DateRecord 
AND mindates.ID = substraction.ID 
SET t1.numberToUpdate = t1.numberToCheck - substractions.NumberToCheck 
WHERE substraction.NumberToCheck > 0 
--your questions is ambigious here: did you mean this one should be greater than 0, or should t1.NumberToCheck > 0 ? 
AND t1.DateRecord <> mindates.mindate 
--Assuming that you don't want to update the record with the lowest date. 

Примечание: Это предполагает, что DateRecord в сочетании с идентификатором уникален, что не является g гарантируется вашей структурой. Я боюсь, что с этой табличной компоновкой другого пути нет.

+0

Это не будет работать из-за ошибки синтаксиса, я полагаю, вы не можете иметь AS в инструкции обновления? –

+0

И DateRecord в сочетании с ID должен быть уникальным, да :) t1.NumberToCheck должен быть> 0 также :) –

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