题目:
(1)写出一个SQL 查询语句,计算每个雇员的奖金。如果一个雇员的id是奇数并且他的名字不是以'M'开头,那么他的奖金是他工资的100%,否则奖金为0。
示例:
输入:
Employees 表:
+-------------+---------+--------+
| employee_id | name | salary |
+-------------+---------+--------+
| 2 | Meir | 3000 |
| 3 | Michael | 3800 |
| 7 | Addilyn | 7400 |
| 8 | Juan | 6100 |
| 9 | Kannon | 7700 |
+-------------+---------+--------+
输出:
+-------------+-------+
| employee_id | bonus |
+-------------+-------+
| 2 | 0 |
| 3 | 0 |
| 7 | 7400 |
| 8 | 0 |
| 9 | 7700 |
+-------------+-------+
解释:
因为雇员id是偶数,所以雇员id 是2和8的两个雇员得到的奖金是0。
雇员id为3的因为他的名字以'M'开头,所以,奖金是0。
其他的雇员得到了百分之百的奖金。
解法一: union:合并查询结果
select employee_id,salary AS bonus
from Employees where employee_id % 2 != 0 and name not like 'M%'
union
select employee_id,salary*0 AS bonus
from Employees where employee_id % 2 = 0 or name like 'M%'
order by employee_id;
解法二: 使用case语句, when 条件 then 条件满足时返回的结果 以end结尾
select employee_id,
case
when mod(employee_id,2) <> 0 and left(name,1) <> 'M' then salary
when mod(employee_id,2) = 0 or left(name,1) = 'M' then 0
end AS bonus
from Employees
order by employee_id
这里再补充一下: mod取余,比如 mod(10,2) 等价于 10%2。 left(name,1):表示取字段name的第一个字母。 <> 等价于 != (不等于号) 后面的 AS bonus 表示给结果取别名
想了解更多此题解法,可以去leetcode原题链接:1873. 计算特殊奖金 - 力扣(Leetcode)
(2)编写一个 SQL 删除语句来 删除 所有重复的电子邮件,只保留一个id最小的唯一电子邮件。以 任意顺序 返回结果表。 (注意: 仅需要写删除语句,将自动对剩余结果进行查询)
示例:
输入:
Person 表:
+----+------------------+
| id | email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
| 3 | john@example.com |
+----+------------------+
输出:
+----+------------------+
| id | email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
+----+------------------+
解释: john@example.com重复两次。我们保留最小的Id = 1。
解法一:使用表自连接
DELETE p1 from Person p1,Person p2 where p1.email = p2.email and p1.id > p2.id
解析:这里如果细心的小伙伴就会发现,这条语句跟我们平时使用的delete删除语法好像不太一样: delete from 表名 where 条件
可能我也是跟大家一样,第一次接触这种写法,解法一语句具体的意思是说: 当where条件满足时,只删除表p1 的数据,跟表p2无关,这里换一种写法,帮助大家更好理解:
DELETE p1 from Person p1
left join Person p2
on p1.email = p2.email and p1.id > p2.id
解法二:
DELETE from Person where id NOT in (
SELECT id from ( SELECT min(id) id from Person group by email ) t
)
解析: SELECT id from ( SELECT min(id) id from Person group by email ) t 表示将(SELECT min(id) id from Person group by email)查询出来的结果作为临时表,取别名 t,这里可能大家会问,干嘛不这样写,不是更简单吗?
# 错误写法
DELETE from Person where id NOT in (
SELECT min(id) id from Person group by email
)
刚开始我也跟大家这样想,这样写看起来的确没什么毛病,而且语句也少了一条,但是当你执行的时候,会发现报错:You can't specify target table 'Person' for update in FROM clause
后来通过查阅资料才知道:SQL不允许同时对同一张表即执行查询又执行删除,也就是这两条语句不能同时发生在同一张表中,所以就需要用到一张临时表
想了解更多此题解法,可以去leetcode原题链接:196. 删除重复的电子邮箱 - 力扣(Leetcode)