使用MIN和GROUP BY时,SQL SELECT的行为不符合预期

问题描述

我有一个简单的在线排行榜,它也将重放编码为字符串。尽管排行榜存储了每个(当前)报告的单圈时间,但是检索php只会返回每个唯一玩家的最佳时间,因此:

SELECT driver,MIN(time),track,replay 
  FROM Laptimes 
 WHERE track = '$track'
 GROUP 
    BY driver 
 ORDER 
    BY MIN(time) ASC 
 LIMIT 10

这正确地报告了最快的时间间隔,但是没有选择与该时间间隔相关的重播。

相反,您只是获得了该驱动程序的第一个重播。

我100%确信重播已正确存储在数据库中,因为如果我删除MIN(),我将获得每个玩家的所有圈速,并且可以毫无问题地观看每个重播。

我似乎无法说服SQL让我以最小的运行时间进行重播。

解决方法

您需要整行,因此需要过滤而不是汇总。一种简单的方法使用相关的子查询:

select l.*
from laptimes l
where
    track = ? 
    l.time = (select min(l1.time) from laptimes l1 where l1.driver = l.driver and l1.track = l.track)

请注意,正如JNevill所说,您的原始查询不是有效的标准SQL,因为selectgroup by子句不一致。 MySQL可能会容忍它(如果您禁用了选项ONLY_FULL_GROUP_BY,这是旧版本中的默认设置),但是您会在group by子句中不存在的非聚合列中获得一个任意值。如下所示编写查询时,这可能更容易理解(等效于您的原始代码-并且是有效的MySQL代码):

SELECT driver,MIN(time),ANY_VALUE(track),ANY_VALUE(replay) 
FROM Laptimes 
WHERE (track='$track') 
GROUP BY driver 
ORDER BY MIN(time) ASC LIMIT 10

注释2:使用准备好的语句!不要将参数混入查询字符串中-这既无效又不安全。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...