使用 FORCE INDEX 确保 table 在计算用户变量之前使用 GROUP BY 和 ORDER BY 排序

using FORCE INDEX to ensure the table is ordered with GROUP BY and ORDER BY before calculating user variables

我正在尝试对第 n 个最高的行求和。

我正在计算一个自行车联赛 table 其中,在一项赛事中,第一快的车手获得 50 分,第二快的 49 分,依此类推....联赛中有 10 场比赛,但只有 8 场比赛是最好的使用结果(这意味着骑手最多可以错过 2 场比赛,而不会在排行榜上出现灾难性的体面) 首先,我需要一个 table,其中每个车手在联赛中所有赛事的成绩都被组合在一起并按最高分的顺序列出,然后计算出一个序号,这样我就可以将 8 个或更少的最佳成绩相加。 所以我用了这个 table select:

set @r := 0, @rn := 0 ;
SELECT 
t.*,
@rn := if(@r = t.id_rider, @rn + 1, 1) as seqnum,
@r :=  t.id_rider as dummy_rider
from results as t 
ORDER BY t.id_rider, t.points desc

其中 table results 是如下视图:

SELECT 
        a.id_rider,
        b.id_event,
        b.race_no,
        b.id_race,
        b.id_race_type,
        b.`position`,
        c.id_league,
        (51 - b.`position`) AS points
    FROM
    wp_dtk_start_sheet a
    JOIN wp_dtk_position_results b ON a.id_event = b.id_event AND a.race_no = b.race_no
    JOIN wp_dtk_league_races c ON b.id_race = c.id_race
    WHERE
    c.id_league = 1
    AND b.`position` IS NOT NULL

这不起作用,因为 seqnum 对于所有结果都是 1。如果我将视图 table 导出到 excel 并使用相同的列和数据创建一个测试 table 它工作正常。我相信出了什么问题是 table 没有在 运行 之前通过变量

ORDER BY t.id_rider, t.points desc 排序

此参考资料:https://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ 声明“此技术几乎是不确定的,因为它依赖于您和我无法直接控制的事物,例如哪些索引 MySQL决定用于分组

此参考建议尝试强制索引使用 id_rider 所以我尝试了:

set @r := 0, @rn := 0 ;
SELECT 
a.id_rider, 
c.id_league, 
(51- b.`position`) as points,
@rn := if(@r = a.id_rider, @rn + 1, 1) as seqnum,
@r :=  a.id_rider as 'set r'
from wp_dtk_start_sheet as a force index (id_rider)
join wp_dtk_position_results as b on a.id_event = b.id_event and a.race_no = b.race_no
join wp_dtk_league_races as c on b.id_race = c.id_race
where c.id_league = 1 and b.`position` is not null   
ORDER BY a.id_rider, points desc

这没有用,我像以前一样为所有行设置了 seqnum =1

我的table结构如下:

table一个-wp_dtk_start_sheet

table b - wp_dtk_position_results

tablec-wp_dtk_league_races

这个堆栈过低的答案也很有帮助,但也有同样的问题:

有人可以帮忙吗?也许我做错了?

如果使用 window functions,解决方案会更加清晰。这允许您指定每个组中行的顺序以便行编号。

SELECT t.*
FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY id_rider ORDER BY points DESC) AS seqnum
  FROM results
) AS t
WHERE t.seqnum <= 8;

支持 MySQL 中的 window 函数是在版本 8.0 中引入的,因此您可能需要升级。但它自 2018 年以来一直是 MySQL 产品的一部分。

Bill 的回答非常有效,但我也将其合并为一个语句,这是组合的 select 命令:

Select
t.id_rider,
sum(points) as total
from 
(SELECT 
a.id_rider, 
c.id_league, 
(51- b.`position`) as points,
ROW_NUMBER() OVER (PARTITION BY id_rider ORDER BY points DESC) AS seqnum
from wp_dtk_start_sheet as a 
join wp_dtk_position_results as b on a.id_event = b.id_event and a.race_no = b.race_no
join wp_dtk_league_races as c on b.id_race = c.id_race
where c.id_league = 1 and b.`position` is not null  ) as t 
where seqnum <= 8
group by id_rider
order by total desc