SQL查询:返回组的最大值记录

问题描述 投票:0回答:5

我有一个类似结构和数据的示例表,如下所示:

+------+---------+-------------+------------+
| 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 |
+------+---------+-------------+------------+

表格中列出了每个学生出现的所有科目中每个学生的合并标记。

请帮助我,写一个查询来提取每个学生获得的MAXIMUM标记(不论学科/其他学生),如下:

按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 |
+------+---------+-------------+------------+
sql oracle aggregate-functions greatest-n-per-group
5个回答
1
投票

使用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)

1
投票

分析函数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>

0
投票

使用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

0
投票

请试试这个。

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

0
投票

你可以使用group bykeep

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()等功能进行聚合功能。根据我的经验,这是非常快的。

© www.soinside.com 2019 - 2024. All rights reserved.