SQL Server: оператор UPDATE, где MAX запрос - PullRequest
3 голосов
/ 17 июня 2011

Я делаю миграцию данных в SQL Server 2008 R2.Я новичок в SQL-Server, но я хорошо знаю Ingres и MySql.

Мне нужно установить «значения по умолчанию» для двух новых полей на «текущие значения» из другой таблицы.Вот моя первая наивная попытка (как я это сделаю в Ingres).

update  rk_risk
set     n_target_probability_ID = a.n_probability_ID
      , n_target_consequence_ID = a.n_consequence_ID
from    rk_assess a
WHERE   a.n_assess_id = (
    SELECT  MAX(n_assess_id)
    FROM    rk_assess a2
    WHERE   a2.n_risk_id = a.n_risk_id
);

Приведенный выше запрос выполняется без ошибок в дальнейшем, но он устанавливает ALL n_target_probability_ID's & n_target_consequence_ID's для то же значение ... что и значение последней оценки OUTRIGHT (в сопоставлении с «последней оценкой ЭТОГО РИСКА»).

Таблица rk_assess содержит полную историю записей оценки заrk_risk s, и моя миссия состоит в том, чтобы «по умолчанию» для нового столбца вероятности и последствий в таблице рисков использовать значения из «текущей» (то есть последней) записи оценки.Столбец rk_assess.n_assess_id представляет собой автоматически увеличивающийся идентификатор (неизменяемый после установки), поэтому max-id всегда должен быть последней записанной записью.

У меня был небольшой поиск, оба в Googleи так, и попробовал несколько другой вариант запроса, но я все еще застрял.Вот пара других эпических неудач со ссылками.

update  rk_risk
set     n_target_probability_ID = (select a.n_probability_ID from rk_assess a where a.n_assess_id = (select max(n_assess_id) from rk_assess a2 where a2.n_risk_id = a.n_risk_id) as ca)
      , n_target_consequence_ID = (select a.n_consequence_ID from rk_assess a where a.n_assess_id = (select max(n_assess_id) from rk_assess a2 where a2.n_risk_id = a.n_risk_id) as ca)
;

/6586174/obnovlenie-servera-sql-iz-izbrannyh

update  r 
set     r.n_target_probability_ID = ca.n_probability_ID
      , r.n_target_consequence_ID = ca.n_consequence_ID
from    rk_risk r
join    rk_assess a
on      a.n_risk_id = r.n_risk_id

select  r.n_risk_id
          , r.n_target_probability_ID, r.n_target_consequence_ID
          , ca.n_probability_ID, ca.n_consequence_ID
from    rk_risk r
join    rk_assess a
on      a.n_risk_id = r.n_risk_id

http://stackoverflow.com/questions/4024489/sql-server-max-statement-returns-multiple-results

UPDATE  rk_risk
SET     n_target_probability_ID = ca.n_probability_ID
      , n_target_consequence_ID = ca.n_consequence_ID
FROM    ( rk_assess a
INNER JOIN (
       SELECT MAX(a2.n_assess_id)
       FROM   rk_assess a2
       WHERE  a2.n_risk_id = a.n_risk_id
) ca -- current assessment

Любые указатели будут с благодарностью.Спасибо всем заранее, даже за то, что прочитали это далеко.

Приветствия.Кит.

Ответы [ 4 ]

6 голосов
/ 17 июня 2011

Как насчет этого:

update  rk_risk
set     n_target_probability_ID = a.n_probability_ID
      , n_target_consequence_ID = a.n_consequence_ID
from    rk_assess a
JOIN    (
    SELECT  n_risk_id, MAX(n_assess_id) max_n_assess_id
    FROM    rk_assess
    GROUP BY n_risk_id
    ) b
ON  a.n_risk_id = b.n_risk_id AND a.n_assess_id = b.max_n_assess_id
WHERE   a.n_risk_id = rk_risk.n_risk_id
3 голосов
/ 17 июня 2011

если вы используете sql 2005 или выше, вы можете в дополнение к ответу Джерада использовать функцию row_number

With b
(
         SELECT  n_risk_id, 
                 n_assess_id,
                 n_probability_ID,
                 n_consequence_ID,
                 row_number() over (partition by n_risk_id order by n_assess_id desc) row
      FROM    rk_assess
)   
update  rk_risk
set     n_target_probability_ID = b.n_probability_ID
      , n_target_consequence_ID = b.n_consequence_ID
from    b
WHERE   a.n_risk_id = rk_risk.n_assess_id
         and row =1 

или CROSS JOIN

update  rk_risk
set     n_target_probability_ID = b.n_probability_ID
      , n_target_consequence_ID = b.n_consequence_ID
from    rh_risk r
      CROSS JOIN
      (
         SELECT  TOP 1
                 n_risk_id, 
                 n_assess_id,
                 n_probability_ID,
                 n_consequence_ID
         FROM    rk_assess
         order by n_assess_id desc
         WHERE   a.n_risk_id = r.n_assess_id)  b 
2 голосов
/ 17 июня 2011

Я попробовал это, похоже, это работает:

update  rk_risk
set     n_target_probability_ID = a.n_probability_ID,
        n_target_consequence_ID = a.n_consequence_ID
from    rk_assess a, rk_risk r
WHERE   a.n_risk_id = r.n_risk_id
and a.n_assess_id in (select MAX(n_assess_id) from rk_assess group by n_risk_id)
1 голос
/ 17 июня 2011

Я обнаружил это из другого вопроса о SO только сегодня.Конструкция UPDATE-FROM не является стандартным SQL, и нестандартная версия MySQL отличается от нестандартной версии Postgres.Из этой проблемы видно, что SQL Server следует за Postgres.

Проблема, как указывает Джерад в своем редактировании, заключается в том, что нет связи между обновляемой таблицей и таблицами в подзапросе.Похоже, что MySQL создает здесь неявное объединение (для имен столбцов? В другом примере SO, это было связано с обработкой двух копий одной и той же таблицы как одной, а не отдельной).

Я не знаю, является ли SQLСервер позволяет создавать окна в подзапросе, но если это так, я думаю, вы хотите

UPDATE  rk_risk
set     n_target_probability_ID = a.n_probability_ID
      , n_target_consequence_ID = a.n_consequence_ID
from
  ( SELECT * FROM
     ( SELECT n_risk_id, n_probability_ID, n_consequence_ID,
              row_number() OVER (PARTITION BY n_risk_id ORDER BY n_assess_ID DESC) AS rn
       FROM rk_assess)
    WHERE rn = 1) AS a
WHERE a.n_risk_id=rk_risk.n_risk_id;
...