LeetCode:SQL语句刷题记录
1、组合两个表
联表查询
select `firstName`,`lastName`,`city`,`state`
from Person p
left join Address a
on p.`PersonId` = a.`PersonId`;
2、超过经理收入的员工
自链接
select a.name as Employee
from Employee as a, Employee as b
where a.managerId = b.id
and a.salary > b.salary;
3、查找重复的电子邮箱
分组 + 过滤
select Email
from Person
group by email
having count(email) > 1;
4、从不订购的客户
联表查询
select name as `Customers`
from Customers as a
left join Orders as b
on a.Id = b.CustomerId
where b.CustomerId is null;
嵌套查询
select name as `Customers`
from Customers
where id not in(
select CustomerId from Orders
);
5、删除重复的电子邮箱
删除
delete p1 from Person p1, Person p2
where p1.email = p2.email
and p1.id > p2.id;
6、上升的温度
自链接
-- datediff():计算两个日期的天数差
select w1.id from Weather as w1, Weather as w2
where datediff(w1.recordDate, w2.recordDate) = 1
and w1.Temperature > w2.Temperature;
7、游戏玩法分析 I
分组 + 聚合函数
select player_id, min(event_date) as first_login
from Activity
group by player_id
8、员工奖金
联表查询
select name, bonus
from Employee e
left join Bonus b
on e.empId = b.empId
where bonus < 1000
or bonus is null;
10、寻找用户推荐人
操作符<> + 逻辑运算符is null
select name from customer
where referee_id <> 2
or referee_id is null;
11、订单最多的客户
分组 + 聚合函数count(*) + 排序 + 分页
select customer_number
from Orders
group by customer_number
order by count(*) desc
limit 1;
12、大的国家
where + or
select name, population, area
from World
where area >= 3000000
or population >= 25000000;
连接子查询union
select name, population, area from World
where area >= 3000000
union
select name, population, area from World
where population >= 25000000;
13、超过5名学生的课
分组 + 过滤
select class from Courses
group by class
having count(*) >= 5;
14、销售员
嵌套查询 + 联表查询
select name from SalesPerson
where sales_id not in(
select sales_id from Orders o
left join Company c
on o.com_id = c.com_id
where c.name = "RED"
);
15、判断三角形
IF函数
select x, y, z, if(x + y > z and y + z > x and z + x > y, "Yes", "No") as triangle
from Triangle;
case ··· when ···
select x, y, z,
case
when x + y > z and y + z > x and z + x > y then "Yes"
else "No"
end
as triangle
from Triangle
16、只出现一次的最大数字
自查询 + 聚合函数max
-- 当从一个子查询或派生表中检索数据时,必须为该子查询或派生表指定别名。
-- 使用聚合函数可以让它出现NULL。
select max(num) as num from (
select num from MyNumbers
group by num
having count(num) = 1
) as t;
17、有趣的电影
聚合函数mod
select * from cinema
where description <> "boring"
and mod(id, 2) = 1
order by rating desc;
18、变更性别
IF函数
update Salary
set sex = if(sex = 'm', 'f', 'm');
19、合作过至少三次的演员和导演
分组 + 分组后过滤
select actor_id, director_id
from ActorDirector
group by actor_id, director_id
having count(*) >= 3;
20、产品销售分析 I
联表查询
select product_name, year, price
from Product p
inner join Sales s
on s.product_id = p.product_id;
21、项目员工 I
ROUND() :用于对指定数字进行四舍五入操作。
select project_id, round(avg(experience_years), 2) as average_years
from Project p, Employee e
where p.employee_id = e.employee_id
group by project_id
22、销售分析III
分组 + 分组后过滤 + 聚合函数min() max()
select p.product_id, p.product_name
from Product p
left join Sales s
on p.product_id = s.product_id
group by p.product_id
having min(sale_date) >= '2019-01-01'
and max(sale_date) <= '2019-03-31';
23、查询近30天活跃用户数
去重distinct + 分组后过滤
select activity_date day, count(distinct user_id) active_users
from Activity
group by activity_date
having activity_date > '2019-06-27'
and activity_date <= '2019-07-27'
24、文章浏览 I
去重distinct + 排序
select distinct author_id id
from Views
where author_id = viewer_id
order by id asc
25、重新格式化部门表
case…when… + sum函数 + 分组 + 排序
当一个单元格中有多个数据时,case when只会提取当中的第一个数据。
以CASE WHEN month=‘Feb’ THEN revenue END 为例,当id=1时,它只会提取month对应单元格里的第一个数据,即Jan,它不等于Feb,所以找不到Feb对应的revenue,所以返回NULL。
那该如何解决单元格内含多个数据的情况呢?答案就是使用聚合函数,聚合函数就用来输入多个数据,输出一个数据的。如SUM()或MAX(),而每个聚合函数的输入就是每一个多数据的单元格。
以SUM(CASE WHEN month=‘Feb’ THEN revenue END) 为例,当id=1时,它提取的Jan、Feb、Mar,从中找到了符合条件的Feb,并最终返回对应的revenue的值,即7000。
select id,
sum(case when month = 'Jan' then revenue end) as Jan_Revenue,
sum(case when month = 'Feb' then revenue end) as Feb_Revenue,
sum(case when month = 'Mar' then revenue end) as Mar_Revenue,
sum(case when month = 'Apr' then revenue end) as Apr_Revenue,
sum(case when month = 'May' then revenue end) as May_Revenue,
sum(case when month = 'Jun' then revenue end) as Jun_Revenue,
sum(case when month = 'Jul' then revenue end) as Jul_Revenue,
sum(case when month = 'Aug' then revenue end) as Aug_Revenue,
sum(case when month = 'Sep' then revenue end) as Sep_Revenue,
sum(case when month = 'Oct' then revenue end) as Oct_Revenue,
sum(case when month = 'Nov' then revenue end) as Nov_Revenue,
sum(case when month = 'Dec' then revenue end) as Dec_Revenue
from Department
group by id
order by id;
26、查询结果的质量和占比
round函数 + 聚合函数 + if函数 + 分组
select query_name,
round(avg(rating / position), 2) quality,
round(sum(if(rating < 3, 1, 0)) / count(*) * 100, 2) poor_query_percentage
from Queries
group by query_name
27、平均售价
round函数 + 聚合函数 + 分组 + 联表查询 + between
select p.product_id, round(sum(price * units)/sum(units), 2) average_price
from Prices p
left join UnitsSold u
on p.product_id = u.product_id
and purchase_date between start_date and end_date
group by p.product_id
28、学生们参加各科测试的次数
联表查询 + 分组 + 排序 + 聚合函数 + cross join:它可以通过将一个表中的每一行与第二个表中的所有行组合来创建一个结果集。
select s.student_id, s.student_name, sub.subject_name,
count(e.subject_name) as attended_exams
from Students s
cross join Subjects sub
left join Examinations e
on s.student_id = e.student_id
and sub.subject_name = e.subject_name
group by s.student_id, sub.subject_name
order by s.student_id ASC;
29、列出指定时间段内所有的下单产品
联表查询 + 分组后过滤 + 聚合函数
select product_name, sum(unit) as unit
from Products p
left join Orders o
on p.product_id = o.product_id
where order_date between '2020-02-01' and '2020-2-29'
group by product_name
having sum(unit) >= 100;
30、使用唯一标识码替换员工ID
联表查询
select unique_id, name
from Employees a
left join EmployeeUNI b
on a.id = b.id
31、排名靠前的旅行者
联表查询 + ifnull()函数 + 分组 + 排序
select name, ifnull(sum(distance), 0) travelled_distance
from Users u
left join Rides r
on u.id = r.user_id
group by u.id
order by sum(distance) desc, name asc;
32、按日期分组销售产品
分组 + 去重 + group_concat()函数
select sell_date,
count(distinct product) num_sold,
group_concat(distinct product) products
from Activities
group by sell_date;
33、查找拥有有效邮箱的用户
正则表达式
‘^’ 表示以后面的字符为开头;‘[]’ 表示括号内任意字符;‘-’ 表示连续;‘*’ 表示重复前面任意字符任意次数;
‘\ ’ 用来转义后面的特殊字符,以表示字符原本的样子,而不是将其作为特殊字符使用;’$’ 表示以前面的字符为结尾。
‘.’(点)这个玩意需要两次转义修饰。
select * from users
where mail REGEXP '^[a-zA-Z][a-zA-Z0-9\_\\.\-]*@leetcode\\.com$'
34、患某种疾病的患者
like模糊查询
select * from Patients
where conditions like '% DIAB1%'
or conditions like 'DIAB1%';
35、进店却未进行过交易的顾客
联表查询 + 分组
select customer_id, count(customer_id) as count_no_trans
from Visits v
left join Transactions t
on v.visit_id = t.visit_id
where transaction_id is null
group by customer_id;
36、银行账户概要 II
联表查询 + 分组后过滤
select name, sum(amount) as balance
from Users u
left join Transactions t
on u.account = t.account
group by name
having sum(amount) > 10000;
37、各赛事的用户注册率
嵌套查询 + round函数 + 聚合函数 + 分组
select
contest_id,
round(100*count(user_id)/(select count(*) from users),2) as percentage
from Register
group by contest_id
order by 2 desc, 1;
38、每台机器的进程平均运行时间
分组 + 聚合函数 + ROUND函数 + IF函数
select
machine_id,
round(avg(if(activity_type='start',-timestamp,timestamp))*2,3) processing_time
from Activity
group by machine_id;
39、修复表中的名字
concat、upper、lower、left、substring函数
select
user_id,
concat(upper(left(name,1)),lower(substring(name,2))) name
from Users
order by user_id;
40、无效的推文
length函数
select tweet_id from Tweets
where length(content) > 15;
41、每天的领导和合伙人
分组 + 聚合函数
select date_id, make_name,
count(distinct lead_id) unique_leads, count(distinct partner_id) unique_partners
from DailySales
group by date_id, make_name;
42、求关注者的数
分组 + 聚合函数
select user_id, count(follower_id) followers_count
from Followers
group by user_id
order by user_id;
43、每位经理的下属员工数量
自链接 + 去重 + 聚合函数 + 分组 + 排序
select distinct a.reports_to employee_id, b.name,
count(a.reports_to) reports_count,
round(avg(a.age)) average_age
from Employees a, Employees b
where a.reports_to = b.employee_id
group by a.reports_to
order by a.reports_to;
44、查找每个员工花费的总时间
分组 + 聚合函数
select event_day day, emp_id, sum(out_time - in_time) total_time
from Employees
group by event_day, emp_id;
45、可回收且低脂的产品
条件查询
select product_id from Products
where low_fats = 'Y'
and recyclable = 'Y';
46、员工的直属部门
分组 + 连接查询union
select employee_id, department_id
from Employee
group by employee_id
having count(*) = 1
union
select employee_id, department_id
from Employee
where primary_flag = 'Y';
47、每个产品在不同商店的价格
列转行 + 连接查询union + 新增的中间列:‘store1’ as store
select product_id, 'store1' store, store1 price
from Products
where store1 is not null
union
select product_id, 'store2' store, store2 price
from Products
where store2 is not null
union
select product_id, 'store3' store, store3 price
from Products
where store3 is not null;
补充:行转列:
SELECT
product_id,
SUM(IF(store = 'store1', price, NULL)) 'store1',
SUM(IF(store = 'store2', price, NULL)) 'store2',
SUM(IF(store = 'store3', price, NULL)) 'store3'
FROM
Products1
GROUP BY product_id ;
48、计算特殊奖金
left函数(用于从左边开始截取指定长度的子字符串) + 排序
也可以使用like查询匹配名字,mod函数取余。
select
employee_id,
if(employee_id % 2 = 1 and left(name, 1) != 'M', salary, 0) bonus
from Employees
order by employee_id;
49、2020年最后一次登录
分组 + 聚合函数 + year函数
select user_id, max(time_stamp) last_stamp
from Logins
where year(time_stamp) = '2020'
group by user_id;
50、丢失信息的雇员
联表查询 + union + 排序
select employee_id
from(
select e.employee_id
from Employees e
left join Salaries s
on e.employee_id = s.employee_id
where salary is null
union
select s.employee_id
from Salaries s
left join Employees e
on e.employee_id = s.employee_id
where name is null
) as r
order by employee_id;
union all + 分组后过滤 + 排序
select employee_id
from(
select employee_id from Employees
union all
select employee_id from Salaries
) as r
group by employee_id
having count(*) = 1
order by employee_id;
51、上级经理已离职的公司员工
子查询
select employee_id
from Employees
where salary < 30000
and manager_id not in (
select employee_id from Employees
)
order by employee_id;
52、每位教师所教授的科目种类的数量
分组 + 聚合函数
select teacher_id, count(distinct subject_id) cnt
from Teacher
group by teacher_id;