圖解面試題:如何分組比較?

【題目】??
現(xiàn)在有三個表,“學生表”,“課程表”,“成績表”。
“學生表”記錄了學生的基本信息,有“學號”、“姓名”、“出生日期”、“性別”。

“成績表”記錄了學生選修課程的成績,包括“學號”,選修的“課程號”以及對應課程的“成績”。

“課程表”記錄了學生選修的課程信息,包括課程號、課程及其對應的“老師號”

“學生表”和“成績表”通過“學號”聯(lián)結,“成績表”和“課程表”通過“課程編號”聯(lián)結。

現(xiàn)在要查找出每門課程中成績最好的學生的姓名和該學生的課程及成績。
需要注意:可能出現(xiàn)并列第一的情況。
【解題思路】
1.確定查詢結果
題目要求每門課程中成績最好的學生的姓名和該學生的課程及成績。可以知道查詢結果是:
select?姓名,課程名稱,成績
查詢結果的“姓名”在“學生表”里,“課程名稱”在“課程表”里,“成績”在“成績表”里。這里涉及到了3個表,所以需要進行多表查詢。
2.如何進行多表查詢?
涉及到多表聯(lián)結,要考慮清楚兩個問題:哪種聯(lián)結類型?如何聯(lián)結?
1)哪種聯(lián)結類型?
多表的聯(lián)結又分為以下幾種類型:
1)左聯(lián)結(left join),聯(lián)結結果保留左表的全部數(shù)據(jù)
2)右聯(lián)結(right join),聯(lián)結結果保留右表的全部數(shù)據(jù)
3)內(nèi)聯(lián)結(inner join),取兩表的公共數(shù)據(jù)
其中“成績表”作為3個表聯(lián)結的中間橋梁,所以要以“成績表”表進行左聯(lián)結,保留左邊表(成績表)里的全部數(shù)據(jù)。

2)如何聯(lián)結?
“學生信息表”和“成績表”都有“學號”,所以聯(lián)結條件為學號。
on a.學號=c.學號
“課程表”和“成績表”都有“課程號”,所以聯(lián)結條件為課程號。
on a.課程號=b.課程號
多表聯(lián)結的sql如下:

3)多表聯(lián)結最終sql
結合前面兩步的sql如下:

運行結果如下:

3.確定查詢條件
題目要求的查詢條件是:每門課程中成績最高的學生。
我們來看這句話里的關鍵詞:
1)“每門課程”,每當出現(xiàn)“每”就是要用分組匯總了,所以是子句(group by課程號)
2)“成績最好” ,就是最大成績了,所以是max(成績)
因此,查詢條件是:

4.合并前面的步驟,確定最終查詢
將第3步的查詢條件,放到第2步多表聯(lián)結的結果中用于篩選出符合條件的數(shù)據(jù)。所以查詢條件如下:

需要注意的是,當兩列同時作為關鍵字段進行條件查詢時,比如這個案例里是(課程號,成績) in,是將兩列合成一個值來查找。比如,“語文”和“90”合并為值“語文 90”。
所以這兩列的順序要和子查詢里列的順序保持一致。如果列的段順序不一樣,比如“90 語文”和“語文 90”就匹配不上,那么查詢結果就是空的了。
最終sql:


【本題考點】
1)考察三個表的聯(lián)結,遇到多表查詢要想起這個圖。

2)考察子查詢。當一個查詢是另一個查詢的條件時則需要用到子查詢。
3)考察分組匯總,當題目中出現(xiàn)“每個”這樣的詞,要想起用分組匯總來實現(xiàn)。
4)考察邏輯思維能力,如何將題目復雜的表達拆解成一個一個子問題,這方面可以“邏輯樹分析方法”來提高。
5)這類型題目屬于在“每個組里比較”,還可以使用“關聯(lián)子查詢”來做,
【舉一反三】
有兩個表,Employee 表用于記錄員工的薪水和在哪個部門,包括員工的Id、員工的姓名(Name)、薪水(Salary) 和?員工所在部門Id(Department Id)。
Department 表用于記錄公司所有部門的信息,包括部門Id,部門名稱(Name)。

找出每個部門工資最高的員工。例如,根據(jù)上述給定的表格,員工(Max)在 IT 部門有最高工資,Henry 在 Sales 部門有最高工資。

思路:
查詢結果包括了兩個表的列名,所以要進行多表聯(lián)結。
1)兩表聯(lián)結
如何聯(lián)結?
因為要查的是所有員工,所以是以員工表(表名Employee)進行左聯(lián)結。
聯(lián)結條件是什么?通過部門Id聯(lián)結。
所以多表聯(lián)結的sql如下:

2)找出每個部門內(nèi)最高的工資作為子查詢從而確定查詢的條件

3)最終sql如下

留道思考題,這類型題目屬于在“每個組里比較”,還可以使用“關聯(lián)子查詢”來做,你會嗎?

