sql - 根据最大值连接表

标签 sql mysql sql-server oracle join

这是我所谈论内容的一个简化示例:

Table: students      exam_results
_____________       ____________________________________
| id | name |       | id | student_id | score |   date |
|----+------|       |----+------------+-------+--------|
|  1 | Jim  |       |  1 |          1 |    73 | 8/1/09 | 
|  2 | Joe  |       |  2 |          1 |    67 | 9/2/09 |
|  3 | Jay  |       |  3 |          1 |    93 | 1/3/09 |
|____|______|       |  4 |          2 |    27 | 4/9/09 |
                    |  5 |          2 |    17 | 8/9/09 |
                    |  6 |          3 |   100 | 1/6/09 |
                    |____|____________|_______|________|

为了这个问题,假设每个学生至少记录了一个考试成绩。

您将如何选择每个学生及其最高分? 编辑:......以及该记录中的其他字段?

预期输出:

_________________________
| name | score |   date |
|------+-------|--------|
|  Jim |    93 | 1/3/09 |
|  Joe |    27 | 4/9/09 |
|  Jay |   100 | 1/6/09 |
|______|_______|________|

欢迎使用所有类型的 DBMS 回答。

最佳答案

回答已编辑的问题(即也获取关联的列)。

在 Sql Server 2005+ 中,最好的方法是使用 ranking/window function结合 CTE ,像这样:

with exam_data as
(
    select  r.student_id, r.score, r.date,
            row_number() over(partition by r.student_id order by r.score desc) as rn
    from    exam_results r
)
select  s.name, d.score, d.date, d.student_id
from    students s
join    exam_data d
on      s.id = d.student_id
where   d.rn = 1;

对于符合 ANSI-SQL 的解决方案,子查询和自连接将起作用,如下所示:

select  s.name, r.student_id, r.score, r.date
from    (
            select  r.student_id, max(r.score) as max_score
            from    exam_results r
            group by r.student_id
        ) d
join    exam_results r
on      r.student_id = d.student_id
and     r.score = d.max_score
join    students s
on      s.id = r.student_id;

这最后一个假设没有重复的 student_id/max_score 组合,如果有和/或你想计划删除它们,你需要使用另一个子查询来加入一些确定性的东西来决定哪个记录拉。例如,假设您不能为同一日期的给定学生拥有多个记录,如果您想根据最近的 max_score 打破平局,您将执行如下操作:

select  s.name, r3.student_id, r3.score, r3.date, r3.other_column_a, ...
from    (
            select  r2.student_id, r2.score as max_score, max(r2.date) as max_score_max_date
            from    (
                        select  r1.student_id, max(r1.score) as max_score
                        from    exam_results r1
                        group by r1.student_id
                    ) d
            join    exam_results r2
            on      r2.student_id = d.student_id
            and     r2.score = d.max_score
            group by r2.student_id, r2.score
        ) r
join    exam_results r3
on      r3.student_id = r.student_id
and     r3.score = r.max_score
and     r3.date = r.max_score_max_date
join    students s
on      s.id = r3.student_id;

编辑:由于 Mark 在评论中的出色表现,添加了适当的重复数据删除查询

关于sql - 根据最大值连接表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1863606/

相关文章:

Python 准备语句。 SELECT IN 的问题

sql - 如何在重叠期间优化具有多个计数(不同...)的配置单元查询?

php - 使用phpv中的echo字段内的html添加数据库中的值

php - 如何在 Wordpress Gravity Forms 中使用 PHP 创建条目

sql - 为什么 json_value 返回 null?

mysql - 这个准备好的语句更新查询不起作用......为什么?

sql - '6/1/201 2' < ' 6/1/2012 0 :00:00. 000' = 真?

php - 将现有 PHP Web 应用程序转换为移动应用程序的最简单方法是什么?

sql - 每个表使用多个索引是否危险?

sql - 合并两个备份文件中的表 - SQL Server