简体   繁体   English

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

[英]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 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 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM