从头开始学MySQL--------子查询(5)

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
(
-- 先查询出来已经选好导师的学生的ID
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 ---

--上述SQL可以被替换为
SELECT 
t_student.id,
t_student.name, 
t_student.teacherId AS 导师ID
FROM t_student
WHERE t_student.teacherId != 1

        根据查询结果来看,好像是有点问题的,因为学霸的teacherId列的值是NULL,NULL != 1 的运算结果是NULL,所以在返回结果中没有显示学霸这个学生记录。这也说明了在嵌套查询中,注意NULL的列可能会影响查询的结果

        本小节希望说明的是,子查询其实就是返回的一个序列,外层查询用子查询的返回结果序列替换掉原来的子查询部分即可。

阅读更多

         目录贴:从头开始学MySQL-------目录帖

        

posted @ 2022-07-17 12:15  小大宇  阅读(21)  评论(0编辑  收藏  举报