Mysql關鍵字之Group By(二)


原文地址,優先更新https://hhe0.github.io

  • 我們在上一節簡單介紹了Mysqlgroup by關鍵字的用法,沒有看過的同學點擊這里了解一下;
  • 文中提到的courses表和相關記錄可以在上一篇文章中自取;
  • 給出的所有sql僅供參考,不一定是效率最高的解法,如果大家有其他的方法,也歡迎提供出來,一起討論。

練習1 那些年一起修過的課

所有的課程

我們的第一反應是可以使用distinct關鍵字實現

SELECT DISTINCT(`class`) FROM `courses`;!

執行的結果如下:

![ScreenClip.png-2.5kB][1]

事實上,我們同樣可以使用group by來實現

SELECT `class` FROM `courses` GROUP BY `class`;

結果與上面相同。因此,我們可以發現group by的一個重要的作用就是枚舉出所有滿足group by條件的組合,間接達到了去重的效果。

練習2 我要修什么課

所有的學生對應修讀的課程

SELECT `student`,`class` 
FROM `courses` 
GROUP BY `student`, `class`; 

執行的結果如下

![ScreenClip.png-10.8kB][2]

練習3 糟糕的成績單

每門課程的排名表

對應的sql為:

SELECT `class`, `student`, `score`
FROM `courses`
ORDER BY `class`, `score` DESC;

執行的結果如下:

![ScreenClip.png-11.7kB][3]

練習4 推選課代表

參考每門課的最高分選擇課代表

對應的sql

SELECT `c`.`class`, `c`.`student`, `c`.`score`
FROM (
SELECT `class`, MAX(`score`) AS `score`
FROM `courses`
GROUP BY `class`
)`T`
INNER JOIN `courses` `c` ON `T`.`class` = `c`.`class` AND `T`.`score` = `c`.`score`;

執行結果如下

![ScreenClip.png-5kB][4]

練習5 獎學金

為每門課的前三名頒獎

我們容易寫出這樣的一個sql

SELECT `class`, `student`
FROM `courses`
GROUP BY `class`, `student`
ORDER BY `class`, `score`
LIMIT 3;

很顯然,這並不是我們想要的結果,至於為什么結果是這個樣子的,大家可以參考上面的order by,這里不再贅述。
正確的sql

SELECT `c1`.`class`, `c1`.`student`, `c1`.`score`
FROM `courses` `c1`
  INNER JOIN `courses` `c2` ON `c1`.`class` = `c2`.`class` AND `c1`.`student` <> `c2`.`student` AND `c1`.`score` > `c2`.`score`
GROUP BY `c1`.`class`, `c1`.`student`
ORDER BY `c1`.`class`, `c1`.`score` DESC;

再提供一種通用的解法

SELECT `c1`.`class`, `c1`.`student`, `c1`.`score`
FROM `courses` `c1`
INNER JOIN `courses` `c2` ON `c1`.`class` = `c2`.`class` AND `c1`.`score` <= `c2`.`score`
GROUP BY `c1`.`class`, `c1`.`student`
HAVING COUNT(*) <= 3
ORDER BY `c1`.`class`, `c1`.`score` DESC;

上述兩個sql執行的結果均為

![ScreenClip.png-9.3kB][6]

兩個sql中為什么一個條件是c1.score>c2.score而另一個是c1.score<=c2.score,以及count(*)<=3而不是count(*)<3,可以細細體會下。

練習6 長板與短板

了解每個學生最擅長的科目和最不擅長的科目

對應的sql

SELECT `T`.`student`, `c`.`class` AS `best_class`, `T`.`max_score` AS `max_score`, `c2`.`class` AS `worst_class`, `T`.`min_score`
FROM (
  SELECT `student`, MAX(`score`) AS `max_score`, MIN(`score`) AS `min_score`
  FROM `courses`
  GROUP BY `student`
) `T`
INNER JOIN `courses` `c` ON `T`.`student` = `c`.`student` AND `c`.`score` = `T`.`max_score`
INNER JOIN `courses` `c2` ON `T`.`student` = `c2`.`student` AND `c2`.`score` = `T`.`min_score`;

執行的結果如下

![ScreenClip.png-9.9kB][7]

練習7 無聊的排序

找到各個分數:Math>Chinese>English>History的同學

對應的sql

SELECT `c1`.`student`, `c1`.`class`, `c1`.`score`, `c2`.`class`, `c2`.`score`, `c3`.`class`, `c3`.`score`, `c4`.`class`, `c4`.`score`
FROM `courses` `c1`
INNER JOIN `courses` `c2` ON `c1`.`student` = `c2`.`student` AND `c2`.`class` = 'Chinese'
INNER JOIN `courses` `c3` ON `c1`.`student` = `c3`.`student` AND `c3`.`class` = 'English'
INNER JOIN `courses` `c4` ON `c1`.`student` = `c4`.`student` AND `c4`.`class` = 'History'
WHERE `c1`.`class` = 'Math' AND `c1`.`score` > `c2`.`score` AND `c2`.`score` > `c3`.`score` AND `c3`.`score` > `c4`.`score`;

執行的結果為

![ScreenClip.png-4.7kB][8]
想到就更新一些有趣的sql~


免責聲明!

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



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