【问题标题】: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

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

【问题讨论】:

    标签: mysql sql database join


    【解决方案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我会在一分钟内创建一个新的stackoverflow问题,以便您获得更多积分!
    【解决方案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;
    

    【讨论】:

      猜你喜欢
      • 2018-03-31
      • 2019-12-31
      • 2019-05-09
      • 1970-01-01
      • 1970-01-01
      • 2020-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多