目录
-
超过经理收入的员工
题目描述:Employee
表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。
+----+-------+--------+-----------+ | Id | Name | Salary | ManagerId | +----+-------+--------+-----------+ | 1 | Joe | 70000 | 3 | | 2 | Henry | 80000 | 4 | | 3 | Sam | 60000 | NULL | | 4 | Max | 90000 | NULL | +----+-------+--------+-----------+
给定 Employee
表,编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。在上面的表格中,Joe 是唯一一个收入超过他的经理的员工。
+----------+ | Employee | +----------+ | Joe | +----------+
解题代码:
SELECT a.Name AS Employee
FROM Employee a,Employee b
WHERE a.ManagerId = b.Id
AND a.Salary > b.Salary;
解题思路:
- FROM 两个一模一样的Employee表 a, b
- WHERE 和 AND的基本用法
-
查找重复的电子邮箱
题目描述:编写一个 SQL 查询,查找 Person
表中所有重复的电子邮箱。
+----+---------+ | Id | Email | +----+---------+ | 1 | a@b.com | | 2 | c@d.com | | 3 | a@b.com | +----+---------+
根据以上输入,你的查询应返回以下结果:
+---------+ | Email | +---------+ | a@b.com | +---------+
说明:所有电子邮箱都是小写字母
解题代码一:
SELECT Email
From (SELECT Email, count(Email) as num
From Person
GROUP BY Email) AS statistic
WHERE num > 1;
解题思路:
括号里的SELECT语句是产生一个临时表,如下
| Email | num |
|---------|-----|
| a@b.com | 2 |
| c@d.com | 1 |
statistic,用来对查询计划进行优化的,一般会统计表中的记录数、表的 大小,字段不同值的数量等。在这里statistic的作用就是作为临时表的别名,这个是不能省略的,如果省略会报错。
GROUP BY 和count一般都会同时出现在一个SELECT语句中。
解题代码二(推荐):
SELECT Email
From Person
GROUP BY Email
having count(Email) > 1;
解题思路:
- 用了having这条语句就避免了创造临时表。
- having 筛选行。
- 只要用了GROUP BY(某列)就可以直接用count(某列)就可以数重复的行数了。
-
从不订购的客户
题目描述:某网站包含两个表,Customers
表和 Orders
表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。
Customers 表:
+----+-------+ | Id | Name | +----+-------+ | 1 | Joe | | 2 | Henry | | 3 | Sam | | 4 | Max | +----+-------+
Orders 表
+----+------------+ | Id | CustomerId | +----+------------+ | 1 | 3 | | 2 | 1 | +----+------------+
例如给定上述表格,你的查询应返回
+-----------+ | Customers | +-----------+ | Henry | | Max | +-----------+
解题代码:
select c.Name AS 'Customers'
from Customers c
where c.Id not in
(
select o.CustomerId from Orders o
);
解题思路:
- not in + 某表的咧
- where xxx not in 表.列
-
删除重复的电子邮箱
题目描述:编写一个 SQL 查询,来删除 Person
表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。
+----+------------------+ | Id | Email | +----+------------------+ | 1 | john@example.com | | 2 | bob@example.com | | 3 | john@example.com | +----+------------------+ Id 是这个表的主键。
例如,在运行你的查询语句之后,上面的Person表返回以下几行
+----+------------------+ | Id | Email | +----+------------------+ | 1 | john@example.com | | 2 | bob@example.com | +----+------------------+
解题代码:
delete p1
from Person p1, Person p2
where p1.Email = p2.Email and p1.Id > p2.Id
解题思路:
经典题,要考。用两个一模一样的表来找出满足条件的行。
-
上升的温度
题目描述:给定一个 Weather
表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id。
+---------+------------------+------------------+ | Id(INT) | RecordDate(DATE) | Temperature(INT) | +---------+------------------+------------------+ | 1 | 2015-01-01 | 10 | | 2 | 2015-01-02 | 25 | | 3 | 2015-01-03 | 20 | | 4 | 2015-01-04 | 30 | +---------+------------------+------------------+
例如,根据上述给定的 Weather
表格,返回如下 Id:
+----+ | Id | +----+ | 2 | | 4 | +----+
解题代码一:
select distinct w1.id
from Weather w1,Weather w2
where w1.RecordDate > w2.RecordDate and DATEDIFF(w1.RecordDate, w2.RecordDate) = 1
and w1.Temperature > w2.Temperature
解题思路:
- 思路和上一道题相似
- 这里用到一个新的关键字 DATEDIFF(date1, date2) == 1表示两个日期相差一天
解题代码二: