求助:查询各赛事最年轻参赛者姓名与年龄的SQL实现
解决赛事最年轻参赛者姓名查询问题
现有三张数据表:
- participant表:
ptcpt_id(参赛者ID)、ptcpt_name(参赛者姓名)、brt_dt(出生日期) - race表:
race_id(赛事ID)、race_name(赛事名称)、race_date(赛事日期) - individual_race_record表:
irr_id(赛事记录ID)、ptcpt_id、race_id、run_time(参赛时长)
需求是查询每个赛事的名称、举办年份,以及该赛事中最年轻参赛者的姓名和年龄;如果同一赛事有多名最年轻参赛者,需要全部展示。
原SQL仅能获取赛事名称、年份和最小年龄,无法拿到参赛者姓名——直接在子查询加ptcpt_id会因为未加入GROUP BY报错,下面提供两种可行的解决方法:
方法一:使用窗口函数(推荐,简洁高效)
窗口函数可以给每个赛事内的参赛者按年龄排序,筛选出年龄最小的(排名为1的),同时支持展示同年龄的所有参赛者:
SELECT race_name, year, COALESCE(ptcpt_name, 'N/A') AS ptcpt_name, COALESCE(CAST(age AS VARCHAR), 'N/A') AS age FROM ( SELECT r.race_name, EXTRACT(YEAR FROM r.race_date) AS year, p.ptcpt_name, EXTRACT(YEAR FROM AGE(p.brt_dt)) AS age, RANK() OVER (PARTITION BY r.race_id ORDER BY AGE(p.brt_dt) ASC) AS age_rank FROM race r LEFT JOIN individual_race_record irr ON r.race_id = irr.race_id LEFT JOIN participant p ON irr.ptcpt_id = p.ptcpt_id ) ranked WHERE age_rank = 1 OR age IS NULL ORDER BY year DESC;
关键说明:
PARTITION BY r.race_id:按赛事ID分组,每个赛事独立计算参赛者年龄排名ORDER BY AGE(p.brt_dt) ASC:按年龄从小到大排序,年龄最小的参赛者排名为1RANK():相同年龄的参赛者会获得相同的排名1,完美满足"多名最年轻参赛者全部展示"的要求- 用
LEFT JOIN保留所有赛事(包括无参赛者的赛事),COALESCE将空值替换为N/A
方法二:先计算赛事最小年龄,再关联匹配
先通过子查询算出每个赛事的最小年龄,再将原表数据关联回去,筛选出年龄等于该赛事最小年龄的参赛者:
SELECT r.race_name, EXTRACT(YEAR FROM r.race_date) AS year, COALESCE(p.ptcpt_name, 'N/A') AS ptcpt_name, COALESCE(CAST(min_ages.min_age AS VARCHAR), 'N/A') AS age FROM race r LEFT JOIN ( SELECT irr.race_id, EXTRACT(YEAR FROM MIN(AGE(p.brt_dt))) AS min_age FROM individual_race_record irr JOIN participant p ON irr.ptcpt_id = p.ptcpt_id GROUP BY irr.race_id ) min_ages ON r.race_id = min_ages.race_id LEFT JOIN individual_race_record irr ON r.race_id = irr.race_id LEFT JOIN participant p ON irr.ptcpt_id = p.ptcpt_id AND EXTRACT(YEAR FROM AGE(p.brt_dt)) = min_ages.min_age ORDER BY year DESC;
关键说明:
- 子查询
min_ages:计算每个赛事的最小参赛年龄 - 关联条件增加
EXTRACT(YEAR FROM AGE(p.brt_dt)) = min_ages.min_age:精准匹配出该赛事中年龄最小的所有参赛者 - 同样用
LEFT JOIN和COALESCE处理无参赛者的赛事场景
内容的提问来源于stack exchange,提问作者Angela Dela Cruz
相关产品推荐
相关产品推荐

