CodeGym /课程 /SQL SELF /INNOT IN 过滤数据

INNOT IN 过滤数据

SQL SELF
第 13 级 , 课程 2
可用

想象一下,你在大学的数据库里工作,需要找出正在上特定课程的学生。比如“编程”、“数学”和“物理”。当然,你可以写一个很长的查询,像这样:

SELECT *
FROM students 
WHERE course = '编程'
   OR course = '数学'
   OR course = '物理';

但说实话,这种写法又累又丑。幸运的是,IN 操作符可以让你把同样的查询写得又短又省事:

SELECT *
FROM students 
WHERE course IN ('编程', '数学', '物理');

是不是有点像魔法?不用一堆 OR,直接让 SQL 查找在这个列表里的值。如果你想查找在列表里的,用 NOT IN —— 查找所有不在这个列表里的

IN 操作符的语法

这是 IN 操作符的通用语法:

SELECT 列
FROM 表
WHERE 列 IN (值1, 值2, 值3, ...);

现在我们来看几个例子。

例子 1:学习多个课程的学生

假设我们有一张 students 表:

id name course
1 Anna 编程
2 Mello 物理
3 Kate 数学
4 Dan 化学
5 Olly 生物

我们想找出所有正在学“编程”、“数学”或“物理”的学生。用 IN

SELECT name, course
FROM students
WHERE course IN ('编程', '数学', '物理');

结果:

name course
Anna 编程
Mello 物理
Kate 数学

你看,IN 操作符让事情简单多了。我们不用写一堆 OR,只要列出我们关心的值就行。

例子 2:不学某些课程的学生

现在,假如你想找出学“编程”、“数学”和“物理”的学生。用 NOT IN

SELECT name, course
FROM students
WHERE course NOT IN ('编程', '数学', '物理');

结果:

name course
Dan 化学
Olly 生物

所以,NOT IN 会返回所有 course不在指定列表里的行。

INNOT IN 搭配子查询

当你需要比较两张表的数据时,INNOT IN 特别有用。比如我们有两张表:

students 表:

id name course_id
1 Anna 101
2 Mello 102
3 Kate 103
4 Dan 104

courses 表:

id name
101 编程
102 物理
103 数学
105 化学

假设我们要找出注册了 courses 表里课程的学生。这里可以用带 IN 的子查询:

SELECT name
FROM students
WHERE course_id IN (
    SELECT id
    FROM courses
);

这个查询怎么工作:子查询 SELECT id FROM courses 会返回所有课程 id。然后 IN 检查 course_id 是否在这个列表里。

结果:

name
Anna
Mello
Kate

为什么 Dan 没出来?因为他的 course_id(104)不在 courses 表里。

NULL 一起用时的注意点

IN 有个很重要的点:如果值列表里有 NULL,可能会影响查询结果。来看个例子。

grades 表:

student_id course_id grade
1 101 A
2 102 NULL
3 103 B

查找成绩在 ('A', 'B', 'C') 里的学生,查询可以这样写:

SELECT student_id
FROM grades
WHERE grade IN ('A', 'B', 'C');

结果:

student_id
1
3

grade 列为 NULL 的那条被忽略了,因为 NULL 不算在任何列表里。

现在假如你用 NOT IN,比如:

SELECT student_id
FROM grades
WHERE grade NOT IN ('A', 'B', 'C');

你可能以为会看到 student_id = 2,但结果是空的!为啥?因为 NULL 和列表里的每个值比较时,结果都是不确定(UNKNOWN)。这种行为很容易让人懵,所以用 NOT IN 时要注意有 NULL 的列。最好加个明确的 NULL 判断:

SELECT student_id
FROM grades
WHERE grade NOT IN ('A', 'B', 'C')
   OR grade IS NULL;

结果:

student_id
2

INNOT IN 的使用建议

IN 让 SQL 更易读
如果你要判断某列是不是在一堆值里,优先用 IN,别写一堆 OR

小心 NOT INNULL
如果数据里有 NULL,可能会有意外结果。用 NOT IN 时最好加上 NULL 的处理。

用索引加速子查询
如果 IN 里用到了子查询,确保子查询里的列有索引,不然性能可能很差。

实际问题例子

想象你在一个电商系统工作。有 ordersusers 两张表。你想找出所有从没下过单的用户。

users 表:

id name
1 Anna
2 Mello
3 Kate
4 Dan

orders 表:

id user_id total
1 1 500
2 3 300

NOT IN 来解决:

SELECT name
FROM users
WHERE id NOT IN (
    SELECT user_id
    FROM orders
);

结果:

name
Mello
Dan

这个查询怎么工作:子查询 SELECT user_id FROM orders 先返回所有下过单的用户 id(1 和 3)。然后 NOT IN 把他们排除掉,只剩没下过单的(Mello 和 Dan)。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION