使用MIN()的MySQL select不会选择所有行

时间:2018-11-26 09:39:32

标签: php mysql select min

背景:我是一名业余程序员,试图为赛车游戏创建个人排行榜。这是通过运行MariaDB的Raspberry Pi完成的。排行榜是从另一个站点上刮取并存储在数据库中的。然后,我的个人运动时间会从游戏中通过UDP接收,并存储在Pi的同一MariaDB中。结果显示在php页面上。用户可以在php页面上选择其他汽车并跟踪组合。我想为每个车手组合显示最佳(最低)圈速。 (玩家名称是官方游戏玩家标签,不允许重复。它们都是唯一的。)

使用这样的SELECT语句,我得到了84行,但是得到了所有自己的运行时间,而我只想展示该车道组合的最佳运行时间。

$sqlstring1="SELECT * FROM laptimes WHERE track = '{$trackselect}' {$choice} AND carname LIKE '{$carselect}' ORDER BY laptime ASC";

我试图像这样使用SELECT,但是后来我只得到54行?我只记录了两个时间,所以没有显示其他人的时间。

$sqlstring1 = "SELECT t1.* FROM laptimes t1
JOIN (
SELECT player, MIN(laptime) AS min_laptime
FROM laptimes 
GROUP BY player
) AS t2 ON t1.player = t2.player AND t1.laptime = t2.min_laptime
WHERE track = '{$trackselect}' {$choice} AND carname LIKE '{$carselect}' 
ORDER BY laptime ASC";

我也尝试了不同的SELECTS,例如LEFT JOIN。 $ trackselect和$ carselect是php页面上下拉菜单中的值,它们似乎在两种情况下均有效。 $ choice值来自php页面上的两个不同按钮。按钮1设置$ choice =“”。按钮2设置$ choice =“ AND玩家喜欢'Maskmagog'”。这仅用于显示我的运动时间。它似乎正在工作。

问题:为什么在第二个SELECT中没有选择某些行?

以下是第一个SELECT的前5个输出:

1.  sel                 Ginetta G40 Junior  00:56.017   
2.  {DFRUK}michaeldimel Ginetta G40 Junior  00:56.149   
3.  Yorkshire Farmer    Ginetta G40 Junior  00:56.709   
4.  piquet              Ginetta G40 Junior  00:56.756   
5.  Oomph               Ginetta G40 Junior  00:56.981   

和第二个SELECT:

1.  Yorkshire Farmer    Ginetta G40 Junior  00:56.709   
2.  saya777             Ginetta G40 Junior  00:57.002   
3.  Lamb4chop™          Ginetta G40 Junior  00:57.067   
4.  Jonge               Ginetta G40 Junior  00:57.250   
5.  NsGTR35             Ginetta G40 Junior  00:57.296   

如您所见,只有“约克郡农民”幸存下来并显示在两个选择中,我不明白为什么。

这是完整的php页面,位于Pastebin上:https://pastebin.com/ALTzfm2S

编辑:由于下面的评论,我终于明白了为什么第二个SELECT无效。它首先选择选手的最小圈速,而不管赛道/赛车如何。然后将其应用到WHERE中,并且将在其他赛车/赛道中设置了最低空转时间的玩家从结果中删除。天哪! :)

编辑2:看来我不能标记多个答案。两种解决方案似乎都能奏效,非常感谢所有参与人员!我无法确定一个答案是否更好/更有用/更正确。

2 个答案:

答案 0 :(得分:1)

您的问题是您的子查询正在返回玩家无论赛道还是汽车的最小圈速。您需要用它返回玩家在其比赛的每条赛道上每辆车的最小圈速,因此您需要将GROUP BY更改为

GROUP BY player, track, carname

,然后还需要将trackcarname添加到子查询SELECTJOIN中。因此您的查询应如下所示:

$sqlstring1 = "SELECT t1.* FROM laptimes t1
JOIN (
SELECT player, track, carname, MIN(laptime) AS min_laptime
FROM laptimes 
GROUP BY player, track, carname
) AS t2 ON t1.player = t2.player AND t1.laptime = t2.min_laptime AND t1.track = t2.track AND t1.carname = t2.carname
WHERE track = '{$trackselect}' {$choice} AND carname LIKE '{$carselect}' 
ORDER BY laptime ASC";

答案 1 :(得分:0)

根据您的要求,您不需要嵌套的SELECT。您可以将条件添加到内部查询中并使用它:

SELECT player, MIN(laptime) AS min_laptime
FROM laptimes 
WHERE track = ?
    AND carname LIKE ?
    AND player LIKE ?
GROUP BY player
ORDER BY laptime ASC

如果不需要所有条件,则可以动态构建sql语句字符串,仅添加所需的条件。然后,绑定所需数量的变量并执行该语句。