查找用户的最低单圈时间排名

Posted

技术标签:

【中文标题】查找用户的最低单圈时间排名【英文标题】:Find the rank of a user's lowest lap time 【发布时间】:2016-09-19 08:15:35 【问题描述】:

我有很多赛车手,他们在不同的赛道上比赛。我想获得他们在每个特定赛道上的最佳单圈时间,并将其与其他用户在该特定赛道上的最佳单圈时间进行排名。我想为所有轨道上的所有用户执行此操作。所以我想返回一个大排行榜。

基本上,如果我有 10 位赛车手,每人在 1 号赛道完成 25 圈,我只想确定每位赛车手的最佳单圈时间,并在每条赛道上对这些时间进行排名。

我想我几乎拥有它,请参阅下面的查询和 SQLFiddle 链接:http://sqlfiddle.com/#!9/64d6c/2

为确保您拥有所有作品,还有一个“tracks.verified”列。这确定轨道是否已被验证。你真的不需要担心这个参数,如果你愿意,可以把它省掉。我指的是这一行:

AND s1.track_id IN (SELECT id FROM tracks WHERE verified=1)

http://sqlfiddle.com/#!9/64d6c/2

SELECT track_id, user_id, duration, @rank := @rank + 1 AS rank FROM
(
  SELECT DISTINCT s1.track_id, s1.user_id, s1.duration
  FROM session_lap_times s1
  LEFT JOIN session_lap_times s2
    ON s1.user_id=s2.user_id
   AND s1.track_id = s2.track_id
   AND s1.duration > s2.duration
  WHERE s2.duration IS NULL
    AND s1.track_id IN (SELECT id FROM tracks WHERE verified=1)
  ORDER BY s1.duration ASC
) zz, (SELECT @rank := 0) z;

这个输出:

+----------+---------+------------------+------+
| track_id | user_id | duration         | rank |
+----------+---------+------------------+------+
|       15 |       2 | 71001.5129995350 |    1 |
|       15 |       1 | 75001.5129995350 |    2 |
|       17 |       1 | 90258.1180334090 |    3 |
|       17 |       2 | 90897.0659971240 |    4 |
+----------+---------+------------------+------+

问题在于它的排名都是相互对立的,而不是每条赛道上的所有排名。这些结果应如下所示:

+----------+---------+------------------+------+
| track_id | user_id | duration         | rank |
+----------+---------+------------------+------+
|       15 |       2 | 71001.5129995350 |    1 |
|       15 |       1 | 75001.5129995350 |    2 |
|       17 |       1 | 90258.1180334090 |    1 |
|       17 |       2 | 90897.0659971240 |    2 |
+----------+---------+------------------+------+

我认为这行是问题所在:

AND s1.track_id IN (SELECT id FROM tracks WHERE verified=1)

因为如果我设置 s1.track_id = 15(例如),这对于单个轨道可以正常工作。只是不是全部。

感谢任何帮助!

编辑:

我正在尝试按 user_id 过滤结果。所以我把你的整个查询放到了一个子查询中。有没有办法做到这一点而不将其放入子查询中?谢谢

select track_id, user_id, duration, rank from (SELECT track_id, user_id,duration, 
  CASE WHEN track_id!=@track THEN @rank:=0 END as reset,
  @rank := @rank + 1 AS rank,
  @track:=track_id
FROM
(
  SELECT DISTINCT s1.track_id, s1.user_id, s1.duration
  FROM session_lap_times s1
  LEFT JOIN session_lap_times s2
    ON s1.user_id=s2.user_id
   AND s1.track_id = s2.track_id
   AND s1.duration > s2.duration
  WHERE s2.duration IS NULL
    AND s1.track_id IN (SELECT id FROM tracks WHERE verified=1)
  ORDER BY s1.duration ASC
) zz, (SELECT @rank := 0, @track := null) z) as x where user_id=1

至于计算我得到的驱动程序查询总数:

SELECT track_id, COUNT(user_id) FROM (SELECT track_id,user_id FROM session_lap_times GROUP BY track_id,user_id) as z GROUP BY track_id

同样,没有子查询有没有更好的方法呢?谢谢! :)

【问题讨论】:

【参考方案1】:
SELECT track_id, user_id, duration, 
  CASE WHEN track_id!=@track THEN @rank:=0 END as reset,
  @rank := @rank + 1 AS rank,
  @track:=track_id
FROM
(
  SELECT DISTINCT s1.track_id, s1.user_id, s1.duration
  FROM session_lap_times s1
  LEFT JOIN session_lap_times s2
    ON s1.user_id=s2.user_id
   AND s1.track_id = s2.track_id
   AND s1.duration > s2.duration
  WHERE s2.duration IS NULL
    AND s1.track_id IN (SELECT id FROM tracks WHERE verified=1)
  ORDER BY s1.duration ASC
) zz, (SELECT @rank := 0, @track := null) z;

用你的小提琴测试过。

引入一个附加变量并在 track_id 更改时重置 rank

【讨论】:

哦哇。惊人的!!是否也可以返回“超出”值的排名?在那条赛道上比赛的所有车手的总数?所以我可以在我的应用程序中显示这样的内容:在 2000 名司机中排名第 1?让我知道它是否不适合在同一个查询中执行此操作,是否应该有自己的查询。 经过进一步思考,我认为在单独的查询中执行此操作可能更容易。然后稍后在我的应用程序代码中匹配结果。您知道可以执行此操作的查询吗?谢谢! 在您发布的原始查询中,有没有办法按 user_id 过滤结果?因此,例如,user_id 1 应该在 track_id 17 上排名 1,在 track_id 15 上排名 2。 是的。应该有适当的 ORDER BY 来定义顺序,然后可以计算排名 嘿,原来查询并没有完全解决问题。当我添加更多样本数据时,它会重置排名。你能看看吗? sqlfiddle.com/#!9/5da399我会在一分钟内创建一个新的***问题,以便您获得更多积分!【参考方案2】:

我发现您的 SQL 令人困惑。我会使用 GROUP BY。

SELECT track_id, user_id, MIN(duration) as best_time
FROM session_lap_times
GROUP BY track_id, user_id
ORDER BY track_id, best_time;

【讨论】:

以上是关于查找用户的最低单圈时间排名的主要内容,如果未能解决你的问题,请参考以下文章

查找在“%Y-%m”中给出最低平均评分的用户

MySQL跨多列排名

在我的 Java 代码中查找最大值和最小值

如何根据 SQL Server 中的最高点和最低时间计算排名

带有单圈时间的秒表 JavaScript(如 iPhone 秒表)

我就是想找个下标,怎么用到二分查找了?