1. 程式人生 > >MYSQL中求每個分組中的最大值

MYSQL中求每個分組中的最大值

求每個分組中的最大值
問題可參考https://segmentfault.com/q/1010000004138670

mysql> select * from test;
+----+-------+-----+-------+
| id | name  | age | class |
+----+-------+-----+-------+
|  1 | wang  |  11 |     3 |
|  2 | qiu   |  22 |     1 |
|  3 | liu   |  42 |     1 |
|  4 | qian  |  20 |     2 |
|  5 | zheng |  20 |     2 |
|  6 | li    |  33 |     3 |
+----+-------+-----+-------+

問題:如何選出每班年齡最大者?要求返回符合要求的一行

  • 嘗試一:
selecet id,name,Max(age),class from test group by class

上面這個寫法是錯誤的,因為
包含group by 的SQL語句,select的列要麼是聚合函式,要麼只能出現在group by 子句中
而id和name不滿足要求,返回的結果會錯位。

  • 嘗試二:group by + join方式
  select t1.id,name,t1.age,t1.class from test as t1,
  (select class
,Max(age)as age from test group by class)as t2 where t1.class= t2.class and t1.age = t2.age

這條語句引用了兩個表(t1 和 t2),語義上相當於內連線(INNER JOIN)。子查詢可以作為一個一次性的檢視(子查詢必須用括號括起來,一般後面接”as 表名”來將子查詢的結果儲存下來 )

  • 嘗試三: 對嘗試二進行優化,一般join的時候小表在前,大表在後
select t1.id,name,t1.age,t1.class from 
(select Max(age)as age,class
from test group by class)as t2 inner join test t1 on t1.age = t2.age and t1.class = t2.class
  • 嘗試四:另一種子查詢方式–巢狀子查詢
select t1.id,name,t1.age,t1.class from test t1 
where t1.age = (select max(age) from test t2 where t2.class = t1.class)

總結

  • 上述嘗試二、三、四均正確,均可以返回最大值有多條情況時的記錄。
  • 在SQL語句中,含有子查詢一般比較慢,應該儘量避免使用子查詢,所以嘗試四要比嘗試二、三慢,應該儘量使用嘗試二、三(即join+group by的形式)

關於Group by

在使用分組和聚合函式時,SELET子句中只能存在以下三種元素:

  • (1)常數

  • (2)聚合函式

  • (3)GROUP BY 子句中指定的列名

在 GROUP BY 子句中不能使用列的別名。

GROUP BY 子句結果的顯示是無限的。

只有 SELECT 子句和 HAVING 子句中能夠使用聚合函式,特別是 WHERE 子句中無法使用。

參考連結

https://segmentfault.com/q/1010000004138670
https://segmentfault.com/a/1190000004157112
https://www.jianshu.com/p/47568113fe73