? 前面我們學習了MySQL簡單的單表查詢。但是我們發現,在很多情況下單表查詢并不能很好的滿足我們的查詢需求。本篇文章會重點講解MySQL中的多表查詢、子查詢和一些復雜查詢。希望本篇文章會對你有所幫助。
文章目錄
一、基本查詢回顧
二、多表查詢
2、1 笛卡爾積
2、2 多表查詢練習
三、自連接
四、子查詢
4、1 單行子查詢
4、2 多行子查詢
4、3 多列子查詢
4、4?在from子句中使用子查詢
五、合并查詢
🙋?♂??作者:@Ggggggtm?🙋?♂?
👀?專欄:MySQL?👀
💥?標題:MySQL復合查詢💥
????寄語:與其忙著訴苦,不如低頭趕路,奮路前行,終將遇到一番好風景???
? 在對本篇文章學習之前,首先說明一下本篇文章所用到表的結構和內容。具體如下:
- 員工表emp:
- 部門表dept:
- 薪水表salgrade:
一、基本查詢回顧
查詢工資高于500或崗位為MANAGER的雇員,同時還要滿足他們的姓名首字母為大寫的J?
? 首先確定,上述所需篩選的信息都在一行表中。其次,分析出 工資 > 500 or job = MANAGER。我們先來查詢出滿足?工資 > 500 or job = MANAGER 的員工。具體如下:
? 同時,我們還需要滿足所查詢到的員工的姓名首字母為大寫的J,很明顯是模糊查詢。具體如下圖:
按照部門號升序而雇員的工資降序排序
? 這個需求就是簡單的排序即可。注意所需排序的先后順序。具體如下圖:
使用年薪進行降序排序
? 首先我們需要計算出來年薪。年薪 = 月薪(sal)*12 + 年終獎(comm)。那么我們直接就對其進行排序即可。但是需要注意的是:NULL并不能參與計算,這時候需要內置函數ifnull來進行判斷其是否為NULL,如果為NULL直接加0即可。?具體如下:
顯示工資最高的員工的名字和工作崗位?
? 我們可以很容易的查找到最高工資是多少,然后再根據最高工資去找對應的員工的名字和工作崗位。具體如下圖:
? 上述用了兩條SQL語句確實能夠查詢出我們想要的結果。但是好像不太優雅。能不能用一條語句將所需結果查詢出來呢?答案是可以的。我們可以用子查詢。什么是子查詢呢?在 MySQL 中,子查詢是指在一個查詢語句中嵌套另一個查詢語句。子查詢可以用于過濾結果集、作為計算字段的數據源、與外部查詢進行比較等多種情況。下面我們用子查詢來解決這個需求。具體如下:
顯示工資高于平均工資的員工信息?
? 這個題目的需求與上一個題目的需求很相似。我們可以先獲取平均工資,在查詢比平均工資高的員工,一樣是用子查詢。具體如下:
顯示每個部門的平均工資和最高工資
? 我們看到需求是每個部門,那么首先肯定要按部門號進行分組。其次我們再查詢每個部門的平均工資和最高工資。具體如下圖:
顯示平均工資低于2000的部門號和它的平均工資
? 首先我們很容易可以找到各個部門的平均工資,然后只需要再增加一個條件判斷即可。具體如下:
顯示每種崗位的雇員總數,平均工資??
? 注意是每種崗位,所以需要根據job進行分組查詢。具體如下圖:
二、多表查詢
2、1 笛卡爾積
? 在MySQL中,多表查詢的笛卡爾積(Cartesian Product)是指在沒有使用任何條件或連接的情況下,將兩個或多個表中的所有行進行組合的結果集。這種情況通常是在沒有明確指定連接條件或者WHERE子句的情況下進行的查詢,但在實際應用中,很少需要或者希望獲得笛卡爾積結果。
? 以下是一個簡單的說明以及一個示例來解釋笛卡爾積:
笛卡爾積的性質: 笛卡爾積將參與查詢的每個表的所有可能組合都返回,即第一個表的每一行都會與第二個表的每一行進行組合,生成的結果集的行數為各個表行數的乘積。
示例:我們現在將員工表和部門表進行笛卡爾積。具體如下:
其實我們也不難看出,規律就是如下圖:
? 但是往往我們用笛卡爾積所獲取的表有很多的數據冗余。因為它會產生大量的冗余數據并且效率低下。為了避免得到笛卡爾積,我們需要正確地使用連接條件(例如使用where條件來篩選掉無用信息)來明確指定表之間的關聯關系。例如,在對上述的員工表和部門表進行笛卡爾積時,一個員工不可能會有多個部門號,所以只有部門號相同的才算是有效的信息。最終有效結果如下圖:
2、2 多表查詢練習
顯示部門號為 10 的部門名,員工名和工資我們發現員工表中并沒有我們想要的部門名,所以我們需要進行多表查詢。需要將員工表和部門表進行合并查詢。然后在查詢部門號為10的部門名、員工名和工資。具體如下:
這里再說明一下:上述 SQL語句中 from 后 的 t1 和 t2 是對 emp 和 dept 表進行了重命名,后續都可以 用我們重命名的名字去代替表名字。其次是當我們將兩張表拼接到一塊后,表中會有 兩個deptno,所以我們在使用deptno時,需要指定是那個表的。
顯示各個員工的姓名,工資,及工資級別
? ?我們發現工資等級只有在薪資表中有,所以我們需要進行多表查詢。當我們將員工表與薪水表進行笛卡爾積后,發現很多數據是冗余的。只有薪資符合它所在的等級區間才是有效的。所以我們的查尋結果如下:
三、自連接
? 我們上述講解的是兩張不同的表進行連接。那么可以自己與自己的表進行連接嗎?答案是可以的!MySQL中的自連接是指在同一張表中進行連接操作。這種連接通常用于將表中的數據與自身進行比較或者組合。自連接可以通過將表與自身進行別名來實現,從而使得查詢可以使用表中的不同行進行比較和操作。?我們看如下例子:
? 通過上圖我們發現,當進行自連接時,如果不對表進行取別名,那么將不能夠進行自連接。必須對表進行取別名。自連接的使用場景是什么呢?我們看如下例子。
?顯示員工FORD的上級領導的編號和姓名(mgr是員工領導的編號--empno)
? 員工是在emp表中,上級領導也是員工,也在emp表中。我們可能首先會想到用子查詢來解決,相對簡單。具體如下:
? 但是我們也不難發現,要查詢的兩個條件都是在emp表中,那么我們就可以對emp表進行自連接。我們現在把兩張表想象成一張表是員工表,另一張表是領導表。我們現在需要的有效信息是:員工表中的mgr = 領導表中的empno即可。篩選出有效信息后在選擇員工表中的員工為FORD。具體如下:
四、子查詢
? 子查詢的概念在上文中已經解釋過,這里就不再解釋。在子查詢的子句中,子句查詢出的結果可能不止是一行記錄,也有可能是多行記錄,還有就是多列的情況。下面我們一一來分析一下。
4、1 單行子查詢
顯示 SMITH 同一部門的員工? 首先將SMITH的部門號查出,然后再將該部門的所有員工篩選出即可。具體如下:
4、2 多行子查詢
查詢和10號部門的工作崗位相同的雇員的名字,崗位,工資,部門號,但是不包含10自己的? 我們可以先查詢出10號部門的工作崗位,具體如下:
? 然后我們再進行篩選與上圖中崗位相同的雇員的信息。當我們想用子查詢時,發現上圖的崗位并不是一個,那該怎么辦呢?這時候可以用到 in關鍵字。in關鍵字用于檢查某個值是否在一組值中。剛好符合我們的需求。具體如下:
顯示工資比部門30的所有員工的工資高的員工的姓名、工資和部門號? 題目的要求:找出比30號部門所有員工工資都好的員工信息。也就是比30號部門最高工資還要高的部門。我們首先找出30號部門的員工最高工資,再篩選出薪資比它大的即可。具體如下:
? 我們也可以使用all關鍵字。all關鍵字用于比較外部查詢和子查詢返回的所有值。當使用?all關鍵字時,外部查詢的值必須滿足子查詢返回的所有值的條件才會被選中。具體如下:
顯示工資比部門30的任意員工的工資高的員工的姓名、工資和部門號(包含自己部門的員工)注意:題目中的任意員工,是指的只要有比部門30中的員工工資高的即滿足條件。通俗理解:找出比 部門號30的員工中最低工資 高的員工。這時可以用any關鍵字。 any關鍵字用于比較外部查詢和子查詢返回的任意一個值。 當使用 any? 時,外部查詢的值只需要滿足子查詢返回的任意一個值的條件即可被選中。具體如下:![]()
4、3 多列子查詢
? 單行子查詢是指子查詢只返回單列,單行數據;多行子查詢是指返回單列多行數據,都是針對單列而言的,而多列子查詢則是指查詢返回多個列數據的子查詢語句。下面我們來看一個例子。
查詢和 SMITH 的部門和崗位完全相同的所有雇員,不含 SMITH 本人? 我們可以先查詢出來SMITH的部門和崗位。如下圖:
? 我們發現,要和SMITH的部門和崗位完全相同,是多列的情況。這該怎么辦呢?我們看如下:
? 但是題目中還要求了不能包含SMITH本人。所以再把SMITH本人去掉即可。結果如下:
4、4?在from子句中使用子查詢
? 我們之前學到的from后都是跟的表的名字。在from子句中使用子查詢怎么理解呢?使用子查詢無非就是一個查詢語句中嵌套了一個語句。我們就稱之為子句。那么子句查詢出來的結果我們也可看成一張表,可與其他物理上實力存在的表進行連接。這就是在from子句中使用子查詢的意思。下面我們結合實際例子來理解一下。
顯示每個高于自己部門平均工資的員工的姓名、部門、工資、平均工資
? 我們可以很容易得到每個部門的平均工資,具體如下:
? 我們可以把上述所查詢出來的結果當作一個表,再與emp表進行連接即可。具體如下:
? 對我們來說,有用的信息就是emp.deptno = tmp.deptno。那么查詢出來的結果如下:
? 現在我們只需要emp.sal > tmp.平均工資( avg(sal))?即可,就是題目所要求的答案,具體如下:
顯示每個部門的信息(部門名,編號,地址)和人員數量
? 我們發現,部門名和地址都在部門表中,而我們想要統計每個部門的人員數量還需要在emp表中統計。我們先來統計每個部門的人員數量,具體如下:
? 我們再將上述查詢的結果與部門dept表進行連接,得到有用信息如下圖:
? 此時,我們在獲取題目中的所需要的信息就相當容易了。具體如下圖:
查找每個部門工資最高的人的姓名、工資、部門、最高工資? 首先,我們可以很容易的得到每個部門的最高工資,如下圖:
? 但是怎么獲取工資最高的人的信息呢?這時候可以將我們查詢的結果與emp表連接,再獲取該人的信息就可以了。具體如下:
五、合并查詢
? 在MySQL中,合并查詢指的是將多個查詢結果合并成一個結果集的操作。這可以通過使用union、union?all等操作符來實現。以下是對每種操作符的詳細解釋:
union:union操作符用于將兩個或多個select語句的結果合并為一個結果集,并自動去重。
union?all:與union類似,但不會自動去重。
? 下面我們來看幾個實際例子來理解一下。
將工資大于 2500 或職位是 MANAGER 的人找出來? 這個例子我們前面已經做過類似的,不再過多解釋,直接看下圖:
? 我們也可以先將工資大于2500的人找出來,如下:
? 再找出來職位是MANAGER的。如下圖:
? 最后用union將他們兩個合并即可。具體如下:
? 我們再來用union all 將他們合并試試。具體如下圖:
? 從上述的對比中,我們也能看出來union是合并并且去重,union all就只是合并。注意:兩個select合并的前提是必須所查詢出來的列數是相同的。實際中,union并不常用,我們只是了解一下即可。