You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL查询如何标记各场次比赛最快成绩记录

实现方法

不需要为每个场次编写独立子查询,有更简洁的标准SQL实现方案,根据使用的数据库版本选对应写法即可。

方案1:窗口函数写法(推荐,兼容绝大多数主流数据库新版本)

用MIN() OVER()窗口函数可以在保留所有选手明细行的同时,直接计算出对应赛事下每个场次的全局最快用时,不需要额外构建临时表或做关联,逻辑最简洁:

SELECT
    r.id,
    r.race1,
    -- 对比当前选手race1成绩和该场全局最小值,返回布尔值
    r.race1 = MIN(r.race1) OVER(PARTITION BY r.race_id) AS race1_fastest,
    r.race2,
    r.race2 = MIN(r.race2) OVER(PARTITION BY r.race_id) AS race2_fastest,
    r.race3,
    r.race3 = MIN(r.race3) OVER(PARTITION BY r.race_id) AS race3_fastest
FROM racer r
WHERE r.race_id = 1;

注意:如果使用Oracle等没有原生布尔类型的数据库,可以用CASE表达式包装返回1/0或自定义标识值,写法通用适配所有支持窗口函数的数据库:

CASE WHEN r.race1 = MIN(r.race1) OVER(PARTITION BY r.race_id) THEN 1 ELSE 0 END AS race1_fastest

这个方案适配MySQL 8.0+、PostgreSQL、SQL Server、SQLite 3.25+等绝大多数主流数据库的现行版本。

方案2:单次聚合子查询写法(兼容不支持窗口函数的旧版本数据库)

如果你用的是不支持窗口函数的旧版本(比如MySQL 5.x),也不需要写三个独立子查询,只需要一次聚合算出三个场次的最快值,做一次关联即可,性能远高于多个独立子查询:

SELECT
    r.id,
    r.race1,
    r.race1 = min_score.min1 AS race1_fastest,
    r.race2,
    r.race2 = min_score.min2 AS race2_fastest,
    r.race3,
    r.race3 = min_score.min3 AS race3_fastest
FROM racer r,
(
    SELECT
        MIN(race1) AS min1,
        MIN(race2) AS min2,
        MIN(race3) AS min3
    FROM racer
    WHERE race_id = 1
) min_score
WHERE r.race_id = 1;

问题说明

之前尝试用min()加CASE、WITH子查询没成功,核心问题是普通聚合函数配合GROUP BY会将多行结果压缩为单行聚合结果,无法返回所有选手的明细数据;窗口函数的OVER子句就是专门为这种「保留明细行同时计算全局/分组聚合值」的场景设计的,不需要额外拆分逻辑。当前场景只有50条左右的选手数据,两种写法的性能差异可以忽略。


内容的提问来源于stack exchange,提问作者user081608

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:12:20