我写这个答案是因为@Taryn 在接受的答案中的第一个/更短的替代方案只有在您只选择 GROUP BY 和 MAX 中使用的列时才有效。用户提出的问题是选择表中的所有列(他使用了 SELECT *)。因此,当您向表中添加另一个第三列时,查询结果中的该列值将不正确。您将从不同的表行中获得混合值。@Taryn 的第二个/更长的替代方案(使用内部联接和子查询)有效,但查询是无用的复杂,在我的用例中比我下面的简单替代方案慢 5 倍。
考虑表questions
:
id | asker
-----------
1 | Bob
2 | Bob
3 | Marley
查询SELECT max(id) as id, asker FROM questions GROUP BY asker ORDER BY id DESC
返回预期:
id | asker
-----------
3 | Marley
2 | Bob
现在考虑另一个表questions
:
id | asker | other
-------------------
1 | Bob | 1st
2 | Bob | 2nd
3 | Marley | 3rd
查询SELECT max(id) as id, asker, other FROM questions GROUP BY asker ORDER BY id DESC
返回意外:
id | asker | other
-------------------
3 | Marley | 3rd
2 | Bob | 1st
...请注意,other
第二行结果的值不正确,因为id=2
来自表格的第二行但other=1st
来自表格的第一行!这就是许多用户在评论 Taryn 的答案时报告该解决方案不起作用的方式。
选择其他列时可能的简单解决方案是使用GROUP BY
+ DESC
:
SELECT id, asker, other FROM questions GROUP BY asker DESC
id | asker | other
-------------------
3 | Marley | 3rd
2 | Bob | 2nd
(见演示:https ://www.db-fiddle.com/f/esww483qFQXbXzJmkHZ8VT/10 )
...但是这个简单的解决方案有一些限制:
- 表必须是 InnoDB(我认为这不是问题,因为您将获得更好的性能,而且 MySQL >= 5.5.5 默认/首选存储引擎已从 MyISAM 更改为 InnoDB)
- 您必须为 GROUP BY 中使用的列创建索引 - 所以
asker
在这种情况下(我认为这不是问题,因为索引适用于这种情况,因此您将获得更好的性能。GROUP BY 通常需要创建 tmp 表但是当索引可用的 tmp 表不会被创建,这样更快)
- 对于 MySQL 5.7 和 8.0,需要禁用 SQL 模式 ONLY_FULL_GROUP_BY(例如
SET SESSION sql_mode = '';
)或ANY_VALUE()
在未聚合的选定列上使用以避免错误 ER_WRONG_FIELD_WITH_GROUP。
- 不幸的是,自 MySQL 8.0 https://dev.mysql.com/worklog/task/?id=8693以来,MySQL 开发人员在 GROUP BY 中删除了对 ASC/DESC 的支持,但幸运的是还有其他选择
GROUP BY col1 ORDER BY col1 ASC/DESC
:
SELECT id, asker, other FROM questions GROUP BY asker ORDER BY asker DESC
id | asker | other
-------------------
3 | Marley | 3rd
2 | Bob | 2nd
(见演示:https ://www.db-fiddle.com/f/esww483qFQXbXzJmkHZ8VT/11 )
...结果与上面相同GROUP BY ... DESC
(不要忘记使用 InnoDB 并创建索引)。