mysql在同一个表的UPDATE中嵌套SELECT

时间:2009-05-27 16:42:40

标签: sql mysql join

基本上我需要做这样的事情......这只是一个例子......但是第一个查询的语法在MySQL中不起作用

update people set prize = '' 
where prize = 'Gold' and class = (select class from people where id = person_id);
update people set prize = 'Gold' where id = <id>;

任何一个班级中只有一人可以获得金奖。我只知道获得金奖的人的person_id。

我试图在第一个查询中删除与person_id在同一类中的任何以前的金奖获奖者。然后在第二个中设置新的金牌获胜者。

我相信我需要使用某种类型的内连接,但我对此并不是百分之百确定。

如果我可以在一个查询中完成所有操作,那会更聪明!

有人可以提供建议吗?

谢谢:)

5 个答案:

答案 0 :(得分:10)

在单个SQL查询中进行复杂更新并不总是最好的。实际上,运行两个简单查询可能更有效。所以一定要对两种解决方案进行基准测试。

MySQL支持多表更新的UPDATE语法扩展。您可以在更新时执行JOIN,而不是使用子查询。

然后,您可以使用IF()函数(或CASE)有条件地将prize值更改为不同的值。

因此,如果您绝对必须使用单个查询,请尝试以下方法:

UPDATE people p1 JOIN people p2 
  ON (p1.class = p2.class AND p2.id = <person_id>)
SET prize = IF(p1.id = <person_id>, 'Gold', '')
WHERE p1.id = <person_id> OR p1.prize = 'Gold';

或者这个替代方案:

UPDATE people p1 JOIN people p2 
  ON (p1.class = p2.class AND p2.id = <person_id>)
SET p1.prize = CASE 
  WHEN p1.id = <person_id> THEN 'Gold'
  WHEN p1.prize = 'Gold' THEN ''
  ELSE p1.prize -- other cases are left as is
 END CASE;

答案 1 :(得分:7)

UPDATE people
SET    prize = CASE WHEN id = @lucky THEN 'Gold' ELSE 'Silver' END
WHERE  class = (
       SELECT  class
       FROM    people
       WHERE   id = @lucky
       )

这将为所有用户授予Silver奖金,但获得@lucky的{​​{1}}人除外。

如果您只需要更新Gold和前冠军,请发出以下命令:

@lucky

答案 2 :(得分:1)

如果您在单一陈述后可以使用CASE运算符?没有使用MySQL,但是像:

UPDATE people
SET prize = CASE
              WHEN 'Gold' AND id != @newid THEN ''
              WHEN '' AND id = @newid THEN 'Gold'
            END 
WHERE class = ( 
                SELECT class 
                FROM people
                WHERE id = @newid 
              )

答案 3 :(得分:0)

你绝对可以创建一个存储过程,将新获奖者的id作为参数。

然后,您可以在一行中调用该存储过程。

我在这里使用MS SQL,但类似于:

CREATE PROC UpdatePrize
  @newid int

AS

UPDATE people
SET prize = '' 
WHERE prize = 'Gold'
AND class = ( SELECT class 
              FROM people
              WHERE id = @newid )

UPDATE people
SET prize = 'Gold'
WHERE id = @newid

GO

答案 4 :(得分:0)

由于您正在进行两次不同的更新,因此无需在一个查询中执行此操作。如果您害怕数据不一致,因为两个查询中的一个可能会失败,您可以使用事务并回滚任何两个查询失败。

您当前的查询完全可读且易于理解,而发布的解决方案远非易读。