基本上我需要做这样的事情......这只是一个例子......但是第一个查询的语法在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在同一类中的任何以前的金奖获奖者。然后在第二个中设置新的金牌获胜者。
我相信我需要使用某种类型的内连接,但我对此并不是百分之百确定。
如果我可以在一个查询中完成所有操作,那会更聪明!
有人可以提供建议吗?
谢谢:)
答案 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)
由于您正在进行两次不同的更新,因此无需在一个查询中执行此操作。如果您害怕数据不一致,因为两个查询中的一个可能会失败,您可以使用事务并回滚任何两个查询失败。
您当前的查询完全可读且易于理解,而发布的解决方案远非易读。