一、是什麼?
1.定義
在一個表達式中調用另一個表達式,就叫子查詢(subQuery),也稱爲子選擇(subSelect),或者內嵌選擇(inner select)
2.本質
- 1.子查詢/嵌套查詢的本質就是where裏面嵌套一個select語句.
- 2.多表連表查詢的一種,參考MySQL(入門篇09)連表查詢(01 Join on ) 詳解.,自關聯.
3. 4種分類
1.分類
分類 | 返回 | 使用 |
---|---|---|
表子查詢 | 返回 N行 N列 | 在FROM語句中使用 |
行子查詢 | 列的集合1行 N列(記做:行只有一行), | 用於 From和 where |
列子查詢 | 返回行的集合N行1列 | from 和 where |
標量子查詢 | 1行1列, |
注意:這個是n行n列是在 (where)語句裏的n行n列,不是查詢總結果的
2.4種子查詢關係組成關係如圖:
二、怎麼用?
1. 三種子查詢方法
關鍵字 | 解釋 | 定義 |
---|---|---|
where | 把內層的結果,作爲外層的比較條件 | |
from | 內層的結果提供給外層再次查詢 | 把子查詢的結果當做一張臨時表,然後對他進行處理 |
exist | 把外層的結果拿到內層看內層的查詢是否成立 | 對外表進行循環,然後對內表進行查詢,和 in()差不多,、但是使用不同(子查詢大就用exist 內層索引,子查詢小就用in 外層索引) |
四、實例分析
1. 建表.
/*
一、建表
1.players爲球員信息基本表,表penalties爲有過罰款記錄的球員信息列表。
2.PENALTIES 是罰款表
*/
CREATE TABLE PLAYERS
(PLAYERNO INTEGER NOT NULL,
NAME CHAR(15) NOT NULL,-- 名稱
INITIALS CHAR(3) NOT NULL,-- 首字母
BIRTH_DATE DATE ,-- 出生時間
SEX CHAR(1) NOT NULL,-- 性別
JOINED SMALLINT NOT NULL,-- 出道時間
STREET VARCHAR(30) NOT NULL, -- 街道
HOUSENO CHAR(4) ,-- 房間號碼
POSTCODE CHAR(6) ,-- 郵編
TOWN VARCHAR(30) NOT NULL,-- 城鎮名稱
PHONENO CHAR(13) ,-- 電話
LEAGUENO CHAR(4) ,-- 社團號碼.
PRIMARY KEY (PLAYERNO));
CREATE TABLE PENALTIES
(PAYMENTNO INTEGER NOT NULL,-- pay method付款方式
PLAYERNO INTEGER NOT NULL,-- 球員號 -主鍵.
PAYMENT_DATE DATE NOT NULL,-- 付款時間
AMOUNT DECIMAL(7,2) NOT NULL,-- 金額
PRIMARY KEY (PAYMENTNO));
2. 數據
INSERT INTO PLAYERS VALUES (2, 'Everett', 'R', '1948-09-01', 'M', 1975, 'Stoney Road','43', '3575NH', 'Stratford', '070-237893', '2411');
INSERT INTO PLAYERS VALUES (6, 'Parmenter', 'R', '1964-06-25', 'M', 1977, 'Haseltine Lane','80', '1234KK', 'Stratford', '070-476537', '8467');
INSERT INTO PLAYERS VALUES (7, 'Wise', 'GWS', '1963-05-11', 'M', 1981, 'Edgecombe Way','39', '9758VB', 'Stratford', '070-347689', NULL);
INSERT INTO PLAYERS VALUES (8, 'Newcastle', 'B', '1962-07-08', 'F', 1980, 'Station Road','4', '6584WO', 'Inglewood', '070-458458', '2983');
INSERT INTO PLAYERS VALUES (27, 'Collins', 'DD', '1964-12-28', 'F', 1983, 'Long Drive','804', '8457DK', 'Eltham', '079-234857', '2513');
INSERT INTO PLAYERS VALUES (28, 'Collins', 'C', '1963-06-22', 'F', 1983, 'Old Main Road','10', '1294QK', 'Midhurst', '010-659599', NULL);
INSERT INTO PLAYERS VALUES (39, 'Bishop', 'D', '1956-10-29', 'M', 1980, 'Eaton Square','78', '9629CD', 'Stratford', '070-393435', NULL);
INSERT INTO PLAYERS VALUES (44, 'Baker', 'E', '1963-01-09', 'M', 1980, 'Lewis Street','23', '4444LJ', 'Inglewood', '070-368753', '1124');
INSERT INTO PLAYERS VALUES (57, 'Brown', 'M', '1971-08-17', 'M', 1985, 'Edgecombe Way','16', '4377CB', 'Stratford', '070-473458', '6409');
INSERT INTO PLAYERS VALUES (83, 'Hope', 'PK', '1956-11-11', 'M', 1982, 'Magdalene Road','16A', '1812UP', 'Stratford', '070-353548', '1608');
INSERT INTO PLAYERS VALUES (95, 'Miller', 'P', '1963-05-14', 'M', 1972, 'High Street','33A', '5746OP', 'Douglas', '070-867564', NULL);
INSERT INTO PLAYERS VALUES (100, 'Parmenter', 'P', '1963-02-28', 'M', 1979, 'Haseltine Lane','80', '6494SG', 'Stratford', '070-494593', '6524');
INSERT INTO PLAYERS VALUES (104, 'Moorman', 'D', '1970-05-10', 'F', 1984, 'Stout Street','65', '9437AO', 'Eltham', '079-987571', '7060');
INSERT INTO PLAYERS VALUES (112, 'Bailey', 'IP', '1963-10-01', 'F', 1984, 'Vixen Road','8', '6392LK', 'Plymouth', '010-548745', '1319');
INSERT INTO PENALTIES VALUES (1, 6, '1980-12-08',100);
INSERT INTO PENALTIES VALUES (2, 44, '1981-05-05', 75);
INSERT INTO PENALTIES VALUES (3, 27, '1983-09-10',100);
INSERT INTO PENALTIES VALUES (4,104, '1984-12-08', 50);
INSERT INTO PENALTIES VALUES (5, 44, '1980-12-08', 25);
INSERT INTO PENALTIES VALUES (6, 8, '1980-12-08', 25);
INSERT INTO PENALTIES VALUES (7, 44, '1982-12-30', 30);
INSERT INTO PENALTIES VALUES (8, 27, '1984-11-12', 75);
效果如圖:
1.players
2.penalties
3.(案例01)表子查詢
(1)目的.獲取編號小於10的男性球員的號碼(使用表子查詢)
(2)圖
(3)代碼
SELECT `playersInner`.`PLAYERNO` AS 球員的號碼
FROM (
SELECT `PLAYERNO`
FROM `players`
WHERE `PLAYERNO` < 10 AND `SEX` = "M"
) AS playersInner ;
- 1.
from 嵌套表必須使用 as給表名字,並且在第一行 select 的時候也不能使用原來的表指定(可以使用給名字的名字)
- 2.from裏面的select是一個 n*n 的表所以叫做表子查詢
SELECT `PLAYERNO`
FROM `players`
WHERE `PLAYERNO` < 10 AND `SEX` = "M"
- 3.效果
(4)(**重點)**複習一下select語法組成
select
【字段】
from
【表】
join
【(可選)添加的其他表】 -- 1.聯合查詢
on
【(可選)添加其他表的條件】
where
【(可選)滿足的條件】-- 2,條件查詢
group by
【(可選)分組】 -- 3.分組
having
【(可選)分組的次要條件】
order by
【排序規則】 -- 4.排序
limit
【分頁】-- 5.分頁
4.(案例02)行子查詢
(1)要求:獲取和100號球員性別相同並且居住在同一城市的球員號碼。
(2)圖:
(3)代碼
-- 要求:獲取和100號球員性別相同並且居住在同一城市的球員號碼。
SELECT `PLAYERNO` AS 球員號碼
FROM `players`
WHERE (`SEX`,`TOWN`) = (
SELECT `SEX`,`TOWN`
FROM `players`
WHERE `PLAYERNO` = 100);
- 1。where 裏面 代表了一行所以叫做 行子查詢
- 2.效果
5.(案例03)標量子查詢
(1)要求:獲取和27號球員出生在同一年的球員的號碼
(2)圖:
(3)代碼
-- (03練習標量子查詢) 獲取和27號球員出生在同一年的球員的號碼
SELECT `PLAYERNO` AS 球員號碼
FROM `players`
WHERE YEAR(`BIRTH_DATE`)=(
SELECT YEAR(`BIRTH_DATE`)
FROM `players`
WHERE `PLAYERNO` = 27)
AND `PLAYERNO` != 27;
- 1。效果
6.(案例04.1)列子查詢 in
(1)要求:獲取球員性別爲女的所有球員的球員號,名字及所在城市。
(2)注意:因爲結果是n行1列,所以不能使用 = >< != 等操作符(使用 in any (some)all替代)
操作符號 | 作用 |
---|---|
in | 在指定項裏,in(項1,項2…) |
any(some) | 和比較操作符號聯合使用,和 or 類似 |
all | 接在比較操作符號的後面, 和 and 類似, |
(3)代碼
-- (04列子查詢練習)獲取性別爲 女的所有的球員的球員號,名字和城市
SELECT `PLAYERNO` AS 球員號,`NAME` AS 名字,`TOWN` AS 城市
FROM `players`
WHERE `PLAYERNO` IN (
SELECT `PLAYERNO`
WHERE `SEX` = "F"
);
- 1.因爲 where 下的select語句的結果的時一個列,所以叫列子查詢.
- 2.效果:
7.(案例04.2)列子查詢 any
(1)要求:獲取至少比同城的另一球員年輕的所有球員的手機號碼,日期和居住城市
(2)代碼
/*
#### 7.(案例04.2)列子查詢
(1)要求:獲取 至少比同城的另一球員年輕的所有球員 的號碼,日期和居住城市
*/
SELECT `PHONENO` AS 號碼,`BIRTH_DATE` AS 出生日期,`TOWN` AS 居住城市
FROM `players` AS p1
WHERE `BIRTH_DATE` > ANY(
SELECT `BIRTH_DATE`
FROM `players` AS p2
WHERE p2.`TOWN` = p1.`TOWN`
);
(3)效果
8.(案例04.3)列子查詢 all
(1)目的:獲取最老球員的號碼,名字及生日。(即出生日期數值小於或等於所有其它球員的球員)
(2)代碼
/*
#### 8.(案例04.3)列子查詢 all
(1)目的:獲取最老球員的 學員號,名字及生日。(即出生日期數值小於或等於所有其它球員的球員)
*/
SELECT `PLAYERNO` AS 學員號,`NAME` AS 名字,`BIRTH_DATE` AS 生日
FROM `players`AS p1
WHERE p1.`BIRTH_DATE` <= ALL(
SELECT p2.`BIRTH_DATE`
FROM `players` AS p2
);
(3)效果:
參考博客
https://blog.csdn.net/JesseYoung/article/details/40108781