题目
某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。
Customers 表:
+----+-------+
| Id | Name |
+----+-------+
| 1 | Joe |
| 2 | Henry |
| 3 | Sam |
| 4 | Max |
+----+-------+
Orders 表:
+----+------------+
| Id | CustomerId |
+----+------------+
| 1 | 3 |
| 2 | 1 |
+----+------------+
例如给定上述表格,你的查询应返回:
+-----------+
| Customers |
+-----------+
| Henry |
| Max |
+-----------+
审题
翻译一下题目,其实不就是要出现在Customers,但是不出现在Orders中的结果
这不就是两表连接中的这种情况,其实不分析出这种情况也很好写
构造数据
CREATE TABLE Customers(
Id INT,
NAME VARCHAR(20));
CREATE TABLE Orders(
Id INT,
CustomerId INT);
INSERT INTO Customers VALUE(1, 'Joe'),(2, 'Henry'),(3, 'Sam'),(4, 'Max');
INSERT INTO Orders VALUE(1, 3),(2,1);
自己的解法
1、审题的思路
SELECT C.`Name` AS Customers
FROM Customers C
LEFT JOIN Orders O
ON C.`Id` = O.`CustomerId`
WHERE O.`Id` IS NULL;
2.子查询也是可以实现的
①、先查出所有有订单的顾客编号
SELECT CustomerId
FROM Orders;
②、选出编号不为①结果的顾客姓名
SELECT
c.`Name` as 'Customers'
FROM
customers AS c
WHERE c.`Id` NOT IN
(SELECT
CustomerId
FROM
Orders);
别的解法
1.左连接的优化
先用子查询将买过东西的顾客id选出来。 在应用left join
SELECT C.`Name` AS Customers
FROM Customers C
LEFT JOIN (SELECT DISTINCT CustomerId FROM Orders) O
ON C.`Id` = O.`CustomerId`
WHERE O.`CustomerId` IS NULL;
EXISTS是布尔运算符,常用于测试子查询。
SELECT
select_list
FROM
a_table
WHERE
[NOT] EXISTS(subquery);
当subquery返回任何行时,EXISTS返回true,否则返回false。
因此得出下述算法。
SELECT
C.`Name` AS Customers
FROM
customers AS C
WHERE NOT EXISTS
(SELECT
o.`CustomerId`
FROM
orders AS o
WHERE C.`Id` = o.`CustomerId`) ;