在一个表达式中调用另一个表达式,就叫子查询(subQuery),也称为子选择(subSelect),或者内嵌选择(inner select)
1.分类
分类 | 返回 | 使用 |
---|---|---|
表子查询 | 返回 N行 N列 | 在FROM语句中使用 |
行子查询 | 列的集合1行 N列(记做:行只有一行), | 用于 From和 where |
列子查询 | 返回行的集合N行1列 | from 和 where |
标量子查询 | 1行1列, |
注意:这个是n行n列是在 (where)语句里的n行n列,不是查询总结果的
2.4种子查询关系组成关系如图:
关键字 | 解释 | 定义 |
---|---|---|
where | 把内层的结果,作为外层的比较条件 | |
from | 内层的结果提供给外层再次查询 | 把子查询的结果当做一张临时表,然后对他进行处理 |
exist | 把外层的结果拿到内层看内层的查询是否成立 | 对外表进行循环,然后对内表进行查询,和 in()差不多,、但是使用不同(子查询大就用exist 内层索引,子查询小就用in 外层索引) |
/*
一、建表
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));
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)目的.获取编号小于10的男性球员的号码(使用表子查询)
(2)图
SELECT `playersInner`.`PLAYERNO` AS 球员的号码
FROM (
SELECT `PLAYERNO`
FROM `players`
WHERE `PLAYERNO` < 10 AND `SEX` = "M"
) AS playersInner ;
from 嵌套表必须使用 as给表名字,并且在第一行 select 的时候也不能使用原来的表指定(可以使用给名字的名字)
SELECT `PLAYERNO`
FROM `players`
WHERE `PLAYERNO` < 10 AND `SEX` = "M"
(4)(**重点)**复习一下select语法组成
select
【字段】
from
【表】
join
【(可选)添加的其他表】 -- 1.联合查询
on
【(可选)添加其他表的条件】
where
【(可选)满足的条件】-- 2,条件查询
group by
【(可选)分组】 -- 3.分组
having
【(可选)分组的次要条件】
order by
【排序规则】 -- 4.排序
limit
【分页】-- 5.分页
(1)要求:获取和100号球员性别相同并且居住在同一城市的球员号码。
(2)图:
(3)代码
-- 要求:获取和100号球员性别相同并且居住在同一城市的球员号码。
SELECT `PLAYERNO` AS 球员号码
FROM `players`
WHERE (`SEX`,`TOWN`) = (
SELECT `SEX`,`TOWN`
FROM `players`
WHERE `PLAYERNO` = 100);
(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)要求:获取球员性别为女的所有球员的球员号,名字及所在城市。
(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)要求:获取至少比同城的另一球员年轻的所有球员的手机号码,日期和居住城市
(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)效果
(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