查找用户的最低单圈时间排名
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;
【讨论】:
以上是关于查找用户的最低单圈时间排名的主要内容,如果未能解决你的问题,请参考以下文章
如何根据 SQL Server 中的最高点和最低时间计算排名