1. 程式人生 > >MySQL5.7從入門到精通--------第七章讀書筆記(4)

MySQL5.7從入門到精通--------第七章讀書筆記(4)

7.5.1  帶ANY、SOME、ALL的子查詢

        子查詢是指一個查詢語句巢狀在另外一個查詢語句中的查詢。

        在SELECT子句中先計運算元查詢,子查詢結果作為來外外層另外一個查詢的過濾條件。即另外一個查詢的查詢條件就是子查詢中返回的資料記錄。

CREATE TABLE tbA(num1 INT NOT NULL);
CREATE TABLE tbB(num2 INT NOT NULL);

INSERT INTO tbA(num1) VALUES(1),(5),(13),(27);
INSERT INTO tbB(num2) VALUES(6),(14),(11),(20);

        ANY與SOME是一個意思,它表示只要滿足任意一個條件,就返回此結果。

SELECT
	num1
FROM
	tbA
WHERE
	num1 > ANY (SELECT num2 FROM tbB)

  

        ALL是滿足所有條件,才返回結果。

SELECT
	num1
FROM
	tbA
WHERE
	num1 > ALL (SELECT num2 FROM tbB)

  

7.5.4  帶IN關鍵詞查詢

         內查詢(巢狀查詢)返回的是一個數據列。

         還是那個選導師的例子。

DROP TABLE IF EXISTS t_teacher;
CREATE TABLE t_teacher(
    id INT(11) PRIMARY KEY AUTO_INCREMENT,
  teacName VARCHAR(255) NOT NULL UNIQUE,
  age  INT(11)
);
 
INSERT INTO t_teacher(teacName,age) VALUES('田教授資料庫原理',44),('秀芳姐C語言',31),
('黃金城通訊原理',36),('韓院長',55);

 

DROP TABLE IF EXISTS t_student;
CREATE TABLE t_student(
    id INT(11),
    name VARCHAR(255),
    teacherId INT(11),
    CONSTRAINT fk_stu_teac FOREIGN KEY(teacherId) REFERENCES t_teacher(id)
);
-- 每個學生選擇一個導師,也可以不選,即沒有導師
INSERT INTO t_student(id,name,teacherId) VALUES(1,'大宇',4),(2,'小雨',3),
(3,'小大宇',2),(4,'學霸',NULL);

 

        如上所示,除了學霸之外的所有學生都已經選好了導師,而學霸的導師是NULL,他要自立門戶。

        現需求:查詢沒有選擇導師的學生,預期結果是查詢出來學霸。

SELECT 
t_student.id,
t_student.name
FROM t_student 
WHERE t_student.id NOT IN
(
SELECT t_student.id
FROM t_student
JOIN t_teacher ON t_student.teacherId = t_teacher.id
)

  

        單獨執行子查詢,看下是什麼結果。

SELECT t_student.id
FROM t_student
JOIN t_teacher ON t_student.teacherId = t_teacher.id

  

        原來子查詢返回的是一個序列,因此原來的SQL可以等價於

SELECT 
t_student.id,
t_student.name
FROM t_student 
WHERE t_student.id NOT IN
(
  1,2,3
)

撥雲見日

        原來,內層的巢狀查詢,或者說是子查詢,返回的原來是一個序列。這就可以解釋巢狀查詢返回多列結果會報錯的原因。

        另外,帶巢狀查詢的SQL語句,其實是分兩步進行的,先執行巢狀查詢並返回序列,再執行外層查詢,條件為序列。

7.5.5  帶比較運算子的子查詢

        現在的需求是:找出不是田教授帶的學生。

        思路是先找到田教授的ID,再在學生表裡面判斷導師ID不是此ID的學生的值。

SELECT 
t_student.id,
t_student.name, 
t_student.teacherId AS 導師ID
FROM t_student
WHERE t_student.teacherId !=
(
SELECT t_teacher.id
FROM t_teacher WHERE t_teacher.teacName LIKE '%田%'
)	

--單獨執行
SELECT t_teacher.id
FROM t_teacher WHERE t_teacher.teacName LIKE '%田%'
--結果為
--- id ---
---  1 ---

        根據查詢結果來看,好像是有點問題的,因為學霸的teacherId列的值是NULL,NULL != 1 的運算結果是NULL,所以在返回結果中沒有顯示學霸這個學生記錄。這也說明了在巢狀查詢中,注意NULL的列可能會影響查詢的結果

        本小節希望說明的是,子查詢其實就是返回的一個序列,外層查詢用子查詢的返回結果序列替換掉原來的子查詢部分即可。