参考:

https://www.lintcode.com/course/21/learn/?chapterId=106&sectionId=692&extraParams=%7B%22moduleSource%22%3A%22lc-course%3A21%22%7D

ANY 操作符的多行子查询


在学习了 IN 操作符实现多行子查询后,我们不禁会产生思考:除了使用 IN 操作符,还有什么方法能进行多行子查询呢?

而这一节我们就能够学习到另一种实现多行子查询的方式:使用 ANY 操作符进行多行子查询。

但在学习之前,我们需要了解一下操作符 ANY 。

操作符 ANY 属于逻辑运算符的一种,与 IN 运算符不同,ANY 必须和其它的比较运算符共同使用,其表示查询结果中的任意一个。

在子查询中使用 ANY ,表示与子查询返回的任何值比较为真,则返回真。

语法:

SELECT `column_name(s)`
FROM `table_name`
WHERE `column_name` OPERATOR
   ANY(SELECT column_name
   FROM table_name)

👇 我们可以通过下面的实例来感受一下 ANY 操作符多行子查询 的用法。

现需要查询学生上课人数超过 “Eastern Heretic” 的任意一门课的学生人数的课程信息,请使用 ANY 操作符实现多行子查询。

本题涉及到多层的嵌套,让我们来一步步对题目进行分析吧!

第一层的父查询为在课程表 courses 中查询满足条件的全部课程信息,这个条件由子查询来完成,即为,查询学生上课人数超过 ”Eastern Heretic“ 的任意一门课的学生人数。这一部分的子查询中需要结合 ANY 操作符实现。之后,再将子查询进行拆分,形成第二层的嵌套子查询。

第二层的父查询为在课程表 courses 中根据教师 id 查询学生上课人数, 其子查询为在教师表 teachers 中查找教师名 name 为 “Eastern Heretic” 的教师 id。

由于我们最终得到的课程信息中肯定不包含 “Eastern Heretic” 的课程,所以我们要在 WHERE 条件中再设置一项:不为 “Eastern Heretic” 所开的课程 。

结合以上,使用 SQL 中子查询的方式如下:

SELECT *
FROM `courses`
WHERE `student_count` > ANY (
        SELECT `student_count`
        FROM `courses`
        WHERE `teacher_id` = (
            SELECT `id`
            FROM `teachers`
            WHERE `name` = 'Eastern Heretic'
        )
    )
    AND `teacher_id` <> (
        SELECT `id`
        FROM `teachers`
        WHERE `name` = 'Eastern Heretic'
    );

本题涉及了多层嵌套,代码也因此而比较长,但经过我们上面的分析是不是就能看懂了呢?

执行输出结果:

mysql> SELECT *
    -> FROM `courses`
    -> WHERE `student_count` > ANY (
    -> SELECT `student_count`
    -> FROM `courses`
    -> WHERE `teacher_id` = (
    -> SELECT `id`
    -> FROM `teachers`
    -> WHERE `name` = 'Eastern Heretic'
    -> )
    -> )
    -> AND `teacher_id` <> (
    -> SELECT `id`
    -> FROM `teachers`
    -> WHERE `name` = 'Eastern Heretic'
    -> );
+----+-------------------------+---------------+------------+------------+
| id | name                    | student_count | created_at | teacher_id |
+----+-------------------------+---------------+------------+------------+
|  1 | Advanced Algorithms     |           880 | 2020-06-01 |          4 |
|  2 | System Design           |          1350 | 2020-07-18 |          3 |
|  3 | Django                  |           780 | 2020-02-29 |          3 |
|  6 | Artificial Intelligence |          1660 | 2018-05-13 |          3 |
|  7 | Java P6+                |           780 | 2019-01-19 |          3 |
+----+-------------------------+---------------+------------+------------+
5 rows in set (0.06 sec)

题目:

https://www.lintcode.com/course/21/learn/2070/description?chapterId=106&sectionId=693&extraParams=%7B%22moduleSource%22%3A%22lc-course%3A21%22%7D&ac=true

请编写 SQL 语句,对于 Southern Emperor 教师的所有课程,从 courses 表和 teachers 表中查询课程创建时间晚于其中任意一门课程创建时间的课程名称(不包含该教师的课程)。

表定义: teachers (教师表)

| 列名 | 类型 | 注释 |
| :—–: | :———-: | :——: |
| id | int unsigned | 主键 |
| name | varchar | 讲师姓名 |
| email | varchar | 讲师邮箱 |
| age | int | 讲师年龄 |
| country | varchar | 讲师国籍 |

表定义: courses(课程表)

| 列名 | 类型 | 注释 |
| :———–: | :———-: | :———-: |
| id | int unsigned | 主键 |
| name | varchar | 课程名称 |
| student_count | int | 学生总数 |
| created_at | date | 课程创建时间 |
| teacher_id | int | 讲师 id |

select name from courses where (created_at) 
> any(select created_at from courses where teacher_id  = (select id from teachers where name='Southern Emperor'))
and (
    teacher_id != (
        select id from teachers where name = 'Southern Emperor'
    )
)

题目2:

查询课程学生数超过最年长教师所有课程学生数的课程信息:

https://www.lintcode.com/course/21/learn/2066?chapterId=106&sectionId=695&extraParams=%7B%22moduleSource%22%3A%22lc-course%3A21%22%7D&ac=true

描述

请编写 SQL 语句,查询教师表 teachers 和课程表 courses,查询最年长的老师所开课程的学生数,最后返回学生数均超过该教师的课程的课程信息。

表定义 1:courses(课程表)

| 列名 | 类型 | 注释 |
| :———— | :———– | :——- |
| id | int unsigned | 主键 |
| name | varchar | 课程名称 |
| student_count | int | 学生数 |
| created_at | date | 创建时间 |
| teacher_id | int | 讲师 id |

表定义 2:teachers(教师表)

| 列名 | 类型 | 注释 |
| :—–: | :———-: | :——: |
| id | int unsigned | 主键 |
| name | varchar | 教师姓名 |
| email | varchar | 教师邮箱 |
| age | int | 教师年龄 |
| country | varchar | 教师国籍 |

select * from courses where student_count > all(
    select student_count from courses where teacher_id in (
        select id from teachers where age=(select max(age) from teachers)
    )
)