SQL Server:UPDATE语句,其中MAX查询

时间:2011-06-17 04:32:41

标签: sql sql-server subquery sql-update max

我在SQL Server 2008 R2中进行数据迁移。我是一个SQL-Server noob,但我非常了解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& n_target_consequence_ID指向相同值 ... OUTRIGHT最后一次评估的结果(与“此次风险的最后评估”相对应)。

rk_assess表包含rk_risk的评估记录的完整历史记录,我的任务是“默认”新的目标概率&风险表的后果列,来自“当前”(即最后一个)评估记录的值。 rk_assess.n_assess_id列是一个自动递增的标识符(一旦设置为不可变),因此max-id应始终是最后输入的记录。

我在google和SO上都进行了一些搜索,尝试了一些不同版本的查询,但我仍然陷入困境。这里有几个史诗般的失败,有参考。

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)
;

http://stackoverflow.com/questions/6256844/sql-server-update-from-select

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 个答案:

答案 0 :(得分:6)

这个怎么样:

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

答案 1 :(得分:3)

如果您使用sql 2005或更高版本,除了Jerad的答案之外,您还可以使用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 :(得分:2)

我试过这个,看起来好像有效:

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)

答案 3 :(得分:1)

我今天从另一个关于SO的问题中发现了这一点。 UPDATE-FROM构造不是标准SQL,MySQL的非标准版本与Postgres的非标准版本不同。从这里的问题来看,看起来SQL Server遵循Postgres。

Jerad在他的编辑中指出,问题在于更新的表与子查询中的表之间没有链接。 MySQL似乎在这里创建了一些隐式连接(在列名上?在另一个SO示例中,它是通过将同一个表的两个副本视为相同而不是单独的)。

我不知道SQL Server是否允许在子查询中进行窗口化,但如果确实如此,我认为你想要

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;