WHERE 子句中带有子查询的 MYSQL UPDATE 查询 - 优化
Posted
技术标签:
【中文标题】WHERE 子句中带有子查询的 MYSQL UPDATE 查询 - 优化【英文标题】:MYSQL UPDATE query with subquery in the WHERE clause - optimization 【发布时间】:2013-07-02 18:23:09 【问题描述】:我正在从事一个需要硬编码排名的项目(请不要标准化 cmets)。该示例有一个分数表。每条得分记录都与一个人和一个特定的游戏迭代有关。我们只想对一个人在游戏的特定迭代中的最高得分进行排名,因为一个人可能在某个时候打破自己的得分并拥有多个记录。以下查询用于标记每个人在特定游戏迭代中的最高分数,以便可以单独对其进行排名。
以下内容非常慢,我想加快速度:
/* Define a game iteration */
SET @VarID=(can be any number from 1-200k);
/* WITHIN A game iteration RESET ALL OF THE PERSONAL BEST */
UPDATE scores m
SET m.personal_best='0'
WHERE VarID = @VarID;
/* IDENTIFY THE "BEST" (in this case the highest score per PeopleID) */
UPDATE scores m
SET m.personal_best='1'
WHERE m.ScoreID IN
(
SELECT _scoreID
FROM
(
SELECT ScoreID as _scoreID FROM scores WHERE VarID = @VarID AND NewScore = ( select max(NewScore) from scores i where i.PeopleID = scores.PeopleID AND VarID = @VarID ) ORDER BY VarID, NewScore DESC
) s
) AND VarID = @VarID;
【问题讨论】:
【参考方案1】:您可以使用 mysql 的多表 UPDATE 语法在不使用子查询的情况下执行此操作。
使用 OUTER JOIN,查找同一个人和 varid 的分数,以及更高的分数。如果没有找到更高的分数(即,如果 m 是得分最高的行),则外连接将使连接表的所有列都为 NULL。
UPDATE scores m
LEFT OUTER JOIN scores AS better
ON m.VarID = better.VarID AND m.PeopleID = better.PeopleID
AND m.NewScore < better.NewScore
SET m.personal_best='1'
WHERE VarID = @VarID
AND better.VarID IS NULL;
但可能有联系;如果此人不止一次达到他们的最佳分数,则会将不止一行标记为他们的最佳分数。如果你想避免这种情况,你必须使用其他一些保证唯一的列来打破平局:
UPDATE scores m
LEFT OUTER JOIN scores AS better
ON m.VarID = better.VarID AND m.PeopleID = better.PeopleID
AND (m.NewScore < better.NewScore OR m.NewScore = better.NewScore AND m.ScoreID < better.ScoreID)
SET m.personal_best='1'
WHERE VarID = @VarID
AND better.VarID IS NULL;
【讨论】:
以上是关于WHERE 子句中带有子查询的 MYSQL UPDATE 查询 - 优化的主要内容,如果未能解决你的问题,请参考以下文章
列子句中带有子查询的 MS SQL Server 数据透视表
Laravel 5.8,在 where 子句中带有 Count(*) 的棘手子查询