【问题标题】:SQL Query: Return Max value record of a GroupSQL查询:返回组的最大值记录
【发布时间】: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 |
+------+---------+-------------+------------+

【问题讨论】:

    标签: sql oracle aggregate-functions greatest-n-per-group


    【解决方案1】:

    您可以使用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() 等功能用于聚合函数。根据我的经验,它非常快。

    【讨论】:

      【解决方案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
            

            【讨论】:

              猜你喜欢
              • 2013-10-31
              • 1970-01-01
              • 1970-01-01
              • 2022-11-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-07-18
              • 1970-01-01
              相关资源
              最近更新 更多