2011-06-17 293 views
3

我正在SQL Server 2008 R2中进行数据迁移。我是SQL-Server noob,但我很了解Ingres和MySql。SQL Server:UPDATE语句,其中MAX查询

我需要将两个新字段的“默认值”设置为另一个表中的“当前值”。这是我第一次天真的尝试(我将如何在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的到相同的值 ...的夺标最后一次评估(如并列为“最后评估这个风险“)。

rk_assess表中包含的评估记录的完整历史rk_risk秒,我的使命是“默认”的新目标概率&后果的风险表中的值列从“当前”(即最后一个)评估记录。 rk_assess.n_assess_id列是一个自动递增的标识符(一次设置不变),所以max-id应该是最后输入的记录。

我已经有一个搜索,无论是在谷歌和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 

任何指针将不胜感激。提前谢谢大家,甚至可以阅读这些。

干杯。基思。

+0

是否必须在一个声明中完成? – WOPR 2011-06-17 04:42:30

回答

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 
+0

评估加入到“父”rk_risk上'rk_assess.n_risk_id' – corlettk 2011-06-17 04:57:17

+0

@corlettk - 尝试上面的更新,我相信这将工作。关键是你需要一个派生表(b),它返回给你每个n_risk_id的最后评估结果,然后你可以在PK上加入rk_assess来获得相关数据。合理? – 2011-06-17 05:01:45

+0

我尝试过你的拳头剪裁,它的行为与我第一次尝试时相同......即所有行都从abolutute-last评估中获得了值......我尝试了修改后的版本,并且** IT WORKS ** !!!谢谢soooooo了。我一直非常沮丧,我认为这很容易,因此没有估计任何时间,结果变得如此棘手。再次感谢。基思。 – corlettk 2011-06-17 05:14:34

1

我所以只是今天发现了这个来自另外一个问题。 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; 
+0

谢谢!这是Conrads第一个解决方案的另一个变种。我以为我知道SQL,但我很快意识到我有很多东西需要学习。 – corlettk 2011-06-17 05:27:02

+0

@CorlettK:我刚刚开始使用窗口和CTE。我认为他们没有得到足够的关注,因为MySQL不支持它们。 – 2011-06-17 05:36:42

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 
+0

我喜欢那第二个版本...使用“从顺序中选择第一个”总是对我来说比“x = max(x)where rest-of-where-clause”对我更“自然”......这是在“order by”子句中有(逻辑上)几个字段时非常麻烦。 – corlettk 2011-06-17 05:20:43

2

我想这一点,看起来是干活g:

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

谢谢你改进格式 – 2011-06-17 05:27:02

+1

谢谢你回答...这是一个团队的事情;-) – corlettk 2011-06-18 08:08:27