mysql - 在计算用户变量之前,使用 FORCE INDEX 确保表按 GROUP BY 和 ORDER BY 排序

标签 mysql greatest-n-per-group window-functions

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

我正在计算自行车联赛表,其中赛事中第一快的骑手获得 50 分,第二快的骑手获得 49 分,依此类推......联盟有 10 项赛事,但只使用了骑手的 8 个最佳成绩(这意味着一名骑手最多可以错过 2 场比赛,而不会在排行榜上出现灾难性的下滑) 首先,我需要一个表格,将联盟中所有赛事的每个骑手的成绩分组在一起并按最高分的顺序列出,然后计算连续的数字,以便我可以将 8 或更少的最佳成绩相加。 所以我使用了这个表选择:

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

其中表结果是如下 View :

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。如果我将 View 表导出到 Excel 并创建一个具有相同列和数据的测试表,则可以正常工作。我认为问题在于,在运行变量之前,该表没有按 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

我的表结构如下:

表a - wp_dtk_start_sheet

table a - wp_dtk_start_sheet

表 b - wp_dtk_position_results

table b - wp_dtk_position_results

表c-wp_dtk_league_races

table c -wp_dtk_league_races

这个 stack overlow 答案也非常有帮助,但也有同样的问题: Sum Top 10 Values

有人可以帮忙吗?也许我的做法完全错误?

最佳答案

如果使用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 中的窗口函数支持是在版本 8.0 中引入的,因此您可能需要升级。但自 2018 年以来,它一直是 MySQL 产品的一部分。

关于mysql - 在计算用户变量之前,使用 FORCE INDEX 确保表按 GROUP BY 和 ORDER BY 排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65512165/

相关文章:

php - 初学者@SQL : SQL query Error

sql - PostgreSQL:同一表中每个项目的前 n 个条目

sql - 具有递归和默认值的树

mysql - MySQL Connector/J JDBC 驱动程序是否支持 Windows native 身份验证插件?

mysql - PhpMyAdmin 不处理触发器

php - 在 MySQL 中,如何将包含 "similar"数据的行返回到我所请求的内容?

MySQL Group By 显示最新结果

mysql - 对 SUM 销售额的 SQL 查询,但仅对给定 GROUP 的 SUM 手头上的最新数据

sql - 复杂的 'Gaps and Islands' 问题

sql - PostgreSQL 窗口函数 : row_number() over (partition col order by col2)