SQL查询:返回组的最大值记录
Posted
技术标签:
【中文标题】SQL查询:返回组的最大值记录【英文标题】:SQL Query: Return Max value record of a Group 【发布时间】:2019-08-02 14:42:01 【问题描述】:我有一个类似结构和数据的示例表,如下所示:
+------+---------+-------------+------------+
| S_ID | S_NAME | SUBJECT | MARK_VALUE |
+------+---------+-------------+------------+
| 1 | Stud | SUB_1 | 50 |
| 2 | Stud | SUB_2 | 60 |
| 3 | Stud | SUB_3 | 70 |
| 4 | Stud_1 | SUB_1 | 40 |
| 5 | Stud_1 | SUB_2 | 50 |
| 6 | Stud_2 | SUB_2 | 40 |
+------+---------+-------------+------------+
表格有每个学生在所有科目中出现的每个学生的综合分数。
请帮我写一个查询来提取每个学生获得的最高分数(不分学科/其他学生),如下所示:
按 S_Name 和 Max(MARK_Value) 分组
+------+---------+-------------+------------+
| S_ID | S_NAME | SUBJECT | MAX_MARK |
+------+---------+-------------+------------+
| 3 | Stud | SUB_3 | 70 |
| 5 | Stud_1 | SUB_2 | 50 |
| 6 | Stud_2 | SUB_2 | 40 |
+------+---------+-------------+------------+
【问题讨论】:
【参考方案1】:您可以使用group by
和keep
:
select max(s_id) keep (dense_rank first order by mark desc) as s_id,
s_name,
max(subject) keep (dense_rank first order by mark desc) as subject,
max(max_mark)
from t
group by s_name;
keep
是一个 Oracle 扩展,它允许将 first_value()
和 last_value()
等功能用于聚合函数。根据我的经验,它非常快。
【讨论】:
【参考方案2】:请试试这个。
Select B.* from @tbl AS B
INNER JOIN(
Select S_Name,MAX(MARK_VALUE) AS MARK_VALUE from @tbl Group by S_Name) AS A
ON A.S_name=B.S_Name
AND A.MARK_VALUE = B.MARK_VALUE
【讨论】:
【参考方案3】:解析函数ROW_NUMBER
可用于按S_NAME
对行进行分组(因为您想获得每个学生的最高分数),并按降序对分数进行排序,以便最大值上升到顶部(即得到 行号 = 1)。
然后选择具有该行号值的行。
SQL> with test (s_id, s_name, subject, mark_value) as
2 (select 1, 'stud', 'sub_1' , 50 from dual union all
3 select 2, 'stud', 'sub_2' , 60 from dual union all
4 select 3, 'stud', 'sub_3' , 70 from dual union all
5 select 4, 'stud_1', 'sub_1', 40 from dual union all
6 select 5, 'stud_1', 'sub_2', 50 from dual union all
7 select 6, 'stud_2', 'sub_2', 40 from dual
8 )
9 select s_id, s_name, subject, mark_value
10 from (select s_id, s_name, subject, mark_value,
11 row_Number() over (partition by s_name order by mark_value desc) rn
12 from test
13 )
14 where rn = 1;
S_ID S_NAME SUBJE MARK_VALUE
---------- ------ ----- ----------
3 stud sub_3 70
5 stud_1 sub_2 50
6 stud_2 sub_2 40
SQL>
如果您的数据库版本不支持分析功能,还有另一个选项不太好,因为它从同一个表中选择了两次。如果表中的行数不多,您不会注意到差异,但在大型数据集上性能会受到影响。
<snip>
9 select s_id, s_name, subject, mark_value
10 from test
11 where (s_name, mark_value) in (select s_name, max(mark_value) max_mark
12 from test
13 group by s_name);
S_ID S_NAME SUBJE MARK_VALUE
---------- ------ ----- ----------
3 stud sub_3 70
5 stud_1 sub_2 50
6 stud_2 sub_2 40
SQL>
【讨论】:
【参考方案4】:使用row_number()
窗口函数
select * from
( select *,
row_number()over(partition by s_name order by MARK_VALUE desc) rn
from table_name
) t where t.rn=1
或者你可以使用关联子查询
select t1.* from table_name t1
where t.MARK_VALUE=(select max(MARK_VALUE) from table_name t2 where t2.S_NAME=t1.S_NAME)
【讨论】:
【参考方案5】:使用row_number()
select * from
(
select *,row_number() over(partition by s_name order by MARK_VALUE desc) as rn
from tablename
)A where rn=1
【讨论】:
以上是关于SQL查询:返回组的最大值记录的主要内容,如果未能解决你的问题,请参考以下文章