题目描述

某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。

Customers 表:

Id Name
1 Joe
2 Henry
3 Sam
4 Max

Orders 表:

Id CustomerId
1 3
2 1

例如给定上述表格,你的查询应返回:

Customer
Henry
Max

相关知识

此题不需要前置知识

解题过程

  1. 分析题意

    • 此题是要找Customers表中涉及到,而Orders表未涉及到的内容,所以是使用左连接
    • Customers与Orders进行左连接,连接条件为Customers.Id与Orders.CustomerId,寻找Orders.Id为空
  2. 编写sql

    SELECT
        `Name` AS Customers
    FROM
        Customers left join Orders ON Customers.Id =Orders.CustomerId
    WHERE 
        Orders.Id IS NULL
    
  3. 提交,运行通过

  4. 查看题解,发现有人用三种方法进行实现

    select c.Name as Customers from Customers c left join Orders o on o.CustomerId = c.Id where o.Id is null;
       
    select c.Name as Customers from Customers c where not exists (select 1 from Orders o where o.CustomerId = c.Id);
       
    select c.Name as Customers from Customers c where c.Id not in (select distinct o.CustomerId from Orders o);
    
    • EXISTS关键字
      • EXISTS 指定一个子查询,检查子查询是否至少会返回一行数据
      • 语法为 EXISTS subquery,返回值不是行的内容,而是Boolean,如果子查询有行则返回True
      • EXISTS在表特别大时效率会高
    • IN关键字
      • value IN (value1, value2 ,……) 相当于 value=value OR value =value2 OR value =…..
      • 如果value在这个集合里,则返回True,否则返回False
      • 这个集合也可以是一个subquery
      • IN关键字和NOT IN关键字要避免使用
        • IN和NOT IN效率低
        • IN和NOT IN容易出错

学习总结

  1. 此题主要考察外连接,外连接中使用了一个关键字ON,设定连接条件,所以再加上WHERE实际上进行了两次筛选。
  2. 子查询
    • 子查询是将本查询的结果作为主查询的数据来源或判断条件的查询
    • 子查询要使用小括号
    • 子查询又叫嵌套查询
    • 子查询常常有
      • SELECT,仅支持标量子查询
      • FROM,支持表子查询
      • WHERE/HAVING,标量子查询、列子查询、行子查询
      • EXISTS 相关子查询
    • 按结果的行数分为
      • 标量子查询 结果只有一行一列
      • 行子查询 结果只有一行多列
      • 列子查询 结果只有一列多行
      • 表子查询 结果一般为多行多列
    • 按父子查询的关系分为
      • 无关子查询:子查询在执行时与父查询没有关系,子查询可以单独执行
      • 相关子查询:子查询在执行时与需查询有关系,子查询不能单独执行
    • 子查询的执行优先于主查询执行,主查询的条件使用到了子查询的结果
    • 子查询最多可嵌套32层