[英]SQL Query: Return Max value record of a Group
I have a sample table with similar structure & data as shown below: 我有一个具有相似结构和数据的示例表,如下所示:
+------+---------+-------------+------------+
| 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 |
+------+---------+-------------+------------+
Table has consolidated mark of each student in all subjects each that student has appeared. 表在每个学生出现的所有科目中都有每个学生的合并标记。
Please help me, to write a query to extract MAXIMUM mark obtained by each student ( irrespective of subject/other students ), as below: 请帮助我,编写一个查询以提取每个学生( 不分学科/其他学生 )获得的MAXIMUM分数,如下所示:
Group by S_Name & Max(MARK_Value)
按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 |
+------+---------+-------------+------------+
use row_number()
window function 使用
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
or you can use corelated subquery 或者您可以使用相关的子查询
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)
Analytic function ROW_NUMBER
can be used to group rows by S_NAME
(as you want to get maximum mark per student), and sort marks in descending order so that the max value raises to the top (ie gets row number = 1). 解析函数
ROW_NUMBER
可用于按S_NAME
对行进行S_NAME
(因为您希望获得每个学生的最高分),并按降序对标记进行排序,以使最大值升至顶部(即,获得行号 = 1)。
Then select rows with that row number value. 然后选择具有该行号值的行。
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>
if your database version doesn't support analytic functions, there's another option which isn't that good as it selects from the same table twice. 如果您的数据库版本不支持分析功能,则还有另一个选项不好,因为它从同一张表中选择了两次。 You won't notice the difference if there aren't that many rows in a table, but performance will suffer on large data sets.
如果表中没有那么多行,您将不会注意到差异,但是在大型数据集上,性能会受到影响。
<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>
Use row_number()
使用
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
Please try this. 请尝试这个。
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
You can use group by
and keep
: 您可以使用
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
is an Oracle extension that allows functionality like first_value()
and last_value()
for aggregation functions. keep
是一个Oracle扩展,允许聚合功能使用first_value()
和last_value()
的功能。 In my experience, it is quite fast. 以我的经验,这是非常快的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.