SQL數據分析之子查詢
子查詢用于為主查詢返回其所需數據,或者對檢索數據進行進一步的限制,通常將一個查詢(子查詢)的結果作為另一個查詢(主查詢)的數據來源或判斷條件,常見的子查詢有WHERE子查詢,HAVING子查詢,FROM子查詢,SELECT子查詢,EXISTS子查詢。
子查詢是一種嵌套在其他 SQL 查詢的 WHERE 子句中的查詢,可以在 SELECT、INSERT、UPDATE 和 DELETE 語句中,同邏輯運算符一起使用。
示例工具:MySQL8.0、Navicat Premium 12
本文講解內容:SQL子查詢
適用范圍:子查詢在SQL數據分析中的應用
使用子查詢必須遵循以下幾個規則:
- 子查詢必須括在圓括號中。
- 子查詢的 SELECT 子句中只能有一個列,除非主查詢中有多個列,用于與子查詢選中的列相比較。
- 子查詢不能使用 ORDER BY,不過主查詢可以。在子查詢中,GROUP BY 可以起到同 ORDER BY 相同的作用。
- 返回多行數據的子查詢只能同多值操作符一起使用,比如 IN 操作符。
- SELECT 列表中不能包含任何對 BLOB、ARRAY、CLOB 或者 NCLOB 類型值的引用。
- 子查詢不能直接用在聚合函數中。
- BETWEEN 操作符不能同子查詢一起使用,但是 BETWEEN 操作符可以用在子查詢中。
創建數據表
通常情況下子查詢都與 SELECT 語句一起使用,其基本語法如下所示:
- SELECT column_name [, column_name ]
- FROM table1 [, table2 ]
- WHERE column_name OPERATOR (SELECT column_name [, column_name ]
- FROM table1 [, table2 ]
- [WHERE])
對于子查詢的數據演示創建兩個表,一個是薪水表,另一個是職位表,并且插入數據。
- #創建薪水表SALARY
- CREATE TABLE SALARY (
- ID VARCHAR ( 10 ),
- NAME VARCHAR ( 10 ),
- AGE VARCHAR ( 10 ),
- ADDRESS VARCHAR ( 10 ),
- SAL INT(10) );
給薪水表插入數據,數據內容如下所示:
- # 給薪水表插入數據
- INSERT INTO SALARY(ID,NAME,AGE,ADDRESS,SAL)
- VALUES
- ('C001','Rmesh',35,'Ahmedabad',2000),
- ('C002','Khilan',25,'Delhi',1500),
- ('C003','Kaushik',23,'Kota',2000),
- ('C004','Chaitali',25,'Mumbai',6500),
- ('C005','Hardik',27,'Bhopal',8500),
- ('C006','Komal',22,'MP',4500),
- ('C007','Tom',26,'MP',5500),
- ('C008','Muffy',24,'Indore',10000);
查詢所有的薪水數據如下所示:
- SELECT * FROM SALARY;
同理創建一個職位表。
- #創建職位表JOB
- CREATE TABLE JOB (
- JID VARCHAR ( 10 ),
- JB VARCHAR ( 10 ));
給職位表插入數據,數據內容如下所示:
- # 給職位表插入數據
- INSERT INTO JOB(JID,JB)
- VALUES
- ('C001','Teacher'),
- ('C002','Docter'),
- ('C003','Teacher'),
- ('C004','Worker'),
- ('C005','Nurse'),
- ('C006','Teacher'),
- ('C007','Docter'),
- ('C008','Teacher');
查詢所有的職位數據如下所示:
- SELECT * FROM JOB;
子查詢過濾
子查詢最常見的使用是在WHERE子句的IN操作符中,以及用來填充計算列。先看一個簡單的例子,要查詢所有醫生的薪水情況,這里首先在職位表中查詢所有醫生的JID,查詢結果如下:
- SELECT JID
- FROM JOB
- WHERE JB='Docter';
然后在薪水表中查詢ID為'C002','C007'的薪水情況,查詢結果如下:
- SELECT SAL
- FROM SALARY
- WHERE ID IN('C002','C007');
這里使用子查詢更加簡便,子查詢從內向外依次處理,在下面的SELECT語句中,MySQL實際上執行了兩個操作,首先查詢返回兩個ID號:C002和C007。
然后,這兩個值以IN操作符要求的逗號分隔的格式傳遞給外部查詢的WHERE子句,可以看到輸出的結果是正確的,并且與前面WHERE子句所返回的值相同。
- SELECT SAL
- FROM SALARY
- WHERE ID IN(SELECT JID
- FROM JOB
- WHERE JB='Docter');
使用子查詢查詢薪水大于8000的員工的所有信息,首先內部查詢薪水大于8000的ID,然后外部使用一個WHERE查詢即可得到結果。
- SELECT *
- FROM SALARY
- WHERE ID IN (SELECT ID
- FROM SALARY
- WHERE SAL > 8000);
作為計算字段使用子查詢
使用子查詢的另一方法是創建計算字段,創建計算字段需要使用聚合函數,例如count,sum,avg,max,min等,這里首先計算平均薪水作為一個內查詢,然后在外部使用WHERE子句進行查詢,得出薪資比平均薪資低的員工的所有信息。
- SELECT *
- FROM SALARY
- WHERE SAL < (SELECT AVG(SAL)
- FROM SALARY);
除使用WHERE過濾,還可以使用HAVING過濾,HAVING子句對分組統計函數進行過濾,也可以在HAVING子句中使用子查詢,要查詢薪資最高的人及其薪資情況,首先內部查詢最高工資,然后外部以人名分組后使用HAVING子句過濾,查詢結果如下。
- SELECT NAME,SAL
- FROM SALARY
- GROUP BY NAME
- HAVING SAL = (SELECT MAX(SAL)
- FROM SALARY);
本文轉載自微信公眾號「大話數據分析」,作者「尚天強」。可以通過以下二維碼關注。轉載本文請聯系大話數據分析公眾號。