我有一个查询,根据某些条件选择一些用户(即,在drivers_standings
表的单元格中具有相同的值,以点表示),并根据它们的最低值({{ 1}})在另一个表(position
)中。
results
但是,我的情况是两者具有相同的值且最低$superquer = "
SELECT SD.driver, MIN(R.position) AS highest_position FROM standings_drivers SD
INNER JOIN results R ON R.driverId = SD.driver
WHERE R.compId='$compId' AND R.eventID>='$firstevent'
AND R.eventID<='$lastevent' AND R.eventSession NOT IN ('T', 'P', 'Q', 'Q1', 'Q2', 'QA')
AND SD.season = '42' AND SD.points='$points_pos'
GROUP BY SD.driver
ORDER BY MIN(R.position)";
。我想要实现的是找到一种方法让它看下一个最低值,然后是下一个,然后是下一个,直到找到差异。
例如,我现在拥有的是:
position
但是,我也有这样的案例:
User A: 56 points, best result 9th
User B: 56 points, best result 6th
User C: 56 points, best result 7th
---> User B, User C, User A
在这种情况下,用户A和用户C将按其第二好结果排序,如果是:
User A: 56 points, best result 4th
User B: 56 points, best result 6th
User C: 56 points, best result 4th
我们会这样订购:
User A: 56 points, best result 4th, second best 5th
User B: 56 points, best result 6th, second best 9th
User C: 56 points, best result 4th, second best 4th
注意:第二个最佳结果可能与最佳结果相同 - 所有用户都参与了多个活动,并且没有什么能阻止他们在多个活动中达到相同的排名。
当然,因为我使用的是sql MIN函数,所以我不知道如何对它进行编码,以便它能找到下一个最佳结果,并且仅适用于那些最佳结果相同的人。
答案 0 :(得分:1)
一种可能性是使用单独的子查询来查询每个用户的第一个和第二个最佳结果。
select SD.driver,
coalesce((select R.Position from results R
where R.driverId = SD.driver and R.compId='$compId'
and R.eventID>='$firstevent' and R.eventID<='$lastevent'
and R.eventSession not in ('T', 'P', 'Q', 'Q1', 'Q2', 'QA')
order by R.Position
limit 1 offset 0), 999999) as best_position,
coalesce((select R2.Position from results R2
where R2.driverId = SD.driver and R2.compId='$compId'
and R2.eventID>='$firstevent' and R2.eventID<='$lastevent'
and R2.eventSession not in ('T', 'P', 'Q', 'Q1', 'Q2', 'QA')
order by R2.Position
limit 1 offset 1), 999999) as second_best_position
from standings_drivers SD
where SD.season = '42' and SD.points='$points_pos'
order by best_position, second_best_position;
未经测试,因此可能包含一些语法错误。
我们使用两个子查询来查找每个驱动程序的所有结果,按位置对结果进行排序,然后使用limit子句分别仅获取第一行或第二行。
我们对子查询的返回结果使用coalesce(),这样当子查询返回NULL(这意味着用户没有进一步的结果)时,该位置将返回为999999。
通过这种方式,我们可以获得一组驱动程序,这些驱动程序的最佳和次佳结果为单独的列,并且可以通过这些列轻松排序。
答案 1 :(得分:1)
以下是使用group_concat
的解决方案。它以每个驱动程序的升序连接位置值,将每个位置格式化为3位数。然后它会在排序时向其附加一个z
,这样结果较少的驱动程序最终会达到平局:
select driverId, score
from
(select driverId,
group_concat(
lpad(position, 3, '0')
order by position) AS score
from results
group by driverId) as drivers
order by score || 'z'
这个解决方案在精度方面没有实际限制,因为它是基于字符串的:一千个位置的系列没有问题。只需确保每个位置使用的位数(3
)设置正确。我认为这不是关于数百名司机的比赛,我猜3
应该是正确的。
使用一个子查询(如上所述)执行此操作将比每个种族(会话)的子查询具有更高的性能。
另请注意,在MySql中,FROM
子句中连接的最大表数为limited to 61,这意味着纯粹的基于连接的解决方案只能在运行之前查看那么多事件(会话)成为例外。
答案 2 :(得分:0)
管理以这种方式为最大数量的事件进行查询循环:
$orderbit = "ORDER BY position1";
$superquer = "SELECT SD.driver,
COALESCE((SELECT R.position FROM results R
WHERE R.driverId = SD.driver AND R.compId='$compId'
AND R.eventID>='$firstevent' AND R.eventID<='$lastevent'
AND R.eventSession NOT IN ('T', 'P', 'Q', 'Q1', 'Q2', 'QA')
ORDER BY R.position
LIMIT 1 OFFSET 0), 999) AS position1";
$i=2;
$max = $totalsessions+1;
while ($i<$max) {
$superquer .= ", COALESCE((SELECT R$i.position FROM results R$i
WHERE R$i.driverId = SD.driver AND R$i.compId='$compId'
AND R$i.eventID>='$firstevent' AND R$i.eventID<='$lastevent'
AND R$i.eventSession NOT IN ('T', 'P', 'Q', 'Q1', 'Q2', 'QA')
ORDER BY R$i.position
LIMIT 1 OFFSET $i), 999) AS position$i";
$orderbit .= ", position$i";
$i++;
}
$superquer .= " FROM standings_drivers SD
WHERE SD.season = '42' AND SD.points='$points_pos'";
$orderbit .= ";";
$querytotl = "$superquer $orderbit";
这是@ NineBerry代码的演变,所以感谢您的所有贡献!