MAX函數和GROUP BY 語句一起使用的一個誤區


使用MAX 函數和 GROUP 的時候會有不可預料的數據被SELECT 出來。
下面舉個簡單的例子:
想知道每個SCOREID 的 數學成績最高的分數。


表信息:
/*DDL Information For - test.lkscore*/
--------------------------------------

Table    Create Table                                                                 
-------  -----------------------------------------------------------------------------
lkscore  CREATE TABLE `lkscore` (                                                     
           `scoreid` int(11) DEFAULT NULL,                                            
           `chinese` int(11) DEFAULT '0',                                             
           `math` int(11) DEFAULT '0',                                               
           KEY `fk_class` (`scoreid`),                                                
           CONSTRAINT `fk_class` FOREIGN KEY (`scoreid`) REFERENCES `lkclass` (`id`)  
         ) ENGINE=InnoDB DEFAULT CHARSET=gb2312                                       




select * from lkscore;

 

query result(12 record

scoreid chinese math
1 90 80
2 100 99
3 29 98
4 87 79
5 89 99
1 49 98
3 98 56
2 76 88
2 80 90
3 90 70
1 90 90
1 67 90



錯誤的SELECT

select scoreid,chinese,max(math) max_math from lkscore group by scoreid;

 

query result(5 records)

scoreid chinese max_math
1 90 98
2 100 99
3 29 98
4 87 79
5 89 99

上面的90明顯不對。

方法一:

select scoreid,chinese,math max_math from 
(
select * from lkscore order by math desc
) T 
group by scoreid;

 

query result(5 records)

scoreid chinese max_math
1 49 98
2 100 99
3 29 98
4 87 79
5 89 99


方法二:


select * from lkscore a where a.math = (select max(math) from lkscore where scoreid = a.scoreid) order by scoreid asc;

 

query result(5 records)

scoreid chinese max_math
1 49 98
2 100 99
3 29 98
4 87 79
5 89 99


這個也是用MAX函數,而且還用到了相關子查詢。
我們來看一下這兩個的效率如何:


explain 
select scoreid,chinese,math max_math from (select * from lkscore order by math desc) T group by scoreid;

 

query result(2 records)

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL (NULL) (NULL) (NULL) (NULL) 12 Using temporary; Using filesort
2 DERIVED lkscore ALL (NULL) (NULL) (NULL) (NULL) 12 Using filesort


很明顯,有兩個FULL TABLE SCAN。



explain 
select scoreid,chinese,math max_math from lkscore a where a.math = 
(select max(math) from lkscore where scoreid = a.scoreid) order by scoreid asc;

 

query result(2 records)

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a index (NULL) fk_class 5 (NULL) 12 Using where
2 DEPENDENT SUBQUERY lkscore ref fk_class fk_class 5 a.scoreid 1 Using where



第二個就用了KEY,子查詢里只掃描了一跳記錄。

很明顯。在這種情況下第二個比第一個效率高點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM