LeetCode会员SQL题题解(简单篇)

说明1:本文使用的MySQL的版本是8.0.17,SQL Server的版本是2008 R2;

说明2:本文中的部分代码来自LeetCode上的评论。

LeetCode SQL题库链接:https://leetcode-cn.com/problemset/database

511. Game Play Analysis I

SQL架构:

Create table Activity (
player_id int, 
device_id int, 
event_date date, 
games_played int
);

Truncate table Activity;

insert into Activity (player_id, device_id, event_date, games_played) values ('1', '2', '2016-03-01', '5');
insert into Activity (player_id, device_id, event_date, games_played) values ('1', '2', '2016-05-02', '6');
insert into Activity (player_id, device_id, event_date, games_played) values ('2', '3', '2017-06-25', '1');
insert into Activity (player_id, device_id, event_date, games_played) values ('3', '1', '2016-03-02', '0');
insert into Activity (player_id, device_id, event_date, games_played) values ('3', '4', '2018-07-03', '5');

Table: Activity

LeetCode会员SQL题题解(简单篇)_第1张图片
(player_id, event_date) is the primary key of this table.
This table shows the activity of players of some game.
Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device.

Write an SQL query that reports the first login date for each player.

The query result format is in the following example:

LeetCode会员SQL题题解(简单篇)_第2张图片

查询代码:

MySQL和SQL Server均适用:

select player_id,min(event_date) as first_login from Activity group by player_id;

512. Game Play Analysis II

表结构与511. Game Play Analysis I相同。

Write a SQL query that reports the device that is first logged in for each player.

The query result format is in the following example:

LeetCode会员SQL题题解(简单篇)_第3张图片

查询代码:

MySQL:

select player_id,device_id from activity
where (player_id,event_date) in
(select player_id,min(event_date) from activity group by player_id)

SQL Server:

select 
    player_id,device_id
from
(
    select 
        player_id,
        device_id,
        row_number() over (partition by player_id order by event_date asc) as rn
    from 
        activity
) as t
where 
    rn=1

534. Game Play Analysis III

表结构与511. Game Play Analysis I相同。

Write an SQL query that reports for each player and date, how many games played so far by the player. That is, the total number of games played by the player until that date. Check the example for clarity.

The query result format is in the following example:

LeetCode会员SQL题题解(简单篇)_第4张图片
For the player with id 1, 5 + 6 = 11 games played by 2016-05-02, and 5 + 6 + 1 = 12 games played by 2017-06-25.
For the player with id 3, 0 + 5 = 5 games played by 2018-07-03.
Note that for each player we only care about the days when the player logged in.

查询代码:

SQL Server:

select player_id,event_date,
sum(games_played) over (partition by player_id order by event_date rows between unbounded
preceding and current row) as games_played_so_far from Activity

此题是典型的求累计和,可以使用sum+over形式的窗口函数实现累计求和的目标。

550. Game Play Analysis IV

表结构与511. Game Play Analysis I相同。

Write an SQL query that reports the fraction of players that logged in again on the day after the day they first logged in, rounded to 2 decimal places. In other words, you need to count the number of players that logged in for at least two consecutive days starting from their first login date, then divide that number by the total number of players.

The query result format is in the following example:

LeetCode会员SQL题题解(简单篇)_第5张图片
Only the player with id 1 logged back in after the first day he had logged in so the answer is 1/3 = 0.33

查询代码:

select 
round( 
(select count(if(datediff(a1.event_date,a2.min_date)=1,1,null)) from activity as a1,
(select player_id,min(event_date) min_date from activity group by player_id)  as a2
where a1.player_id=a2.player_id) / count(distinct(player_id)),2) as fraction
from activity

感觉此题非常经典,count和if函数的结合使用起到了条件计数的作用。

577. 员工奖金

SQL架构:

Create table Employee (EmpId int, Name varchar(255), Supervisor int, Salary int);
Create table Bonus (EmpId int, Bonus int);

Truncate table Employee;

insert into Employee (EmpId, Name, Supervisor, Salary) values ('3', 'Brad', null, '4000');
insert into Employee (EmpId, Name, Supervisor, Salary) values ('1', 'John', '3', '1000');
insert into Employee (EmpId, Name, Supervisor, Salary) values ('2', 'Dan', '3', '2000');
insert into Employee (EmpId, Name, Supervisor, Salary) values ('4', 'Thomas', '3', '4000');

Truncate table Bonus;

insert into Bonus (EmpId, Bonus) values ('2', '500');
insert into Bonus (EmpId, Bonus) values ('4', '2000');

选出所有 bonus < 1000 的员工的 name 及其 bonus。

Employee 表单:

LeetCode会员SQL题题解(简单篇)_第6张图片
empId 是这张表单的主关键字
Bonus 表单:

LeetCode会员SQL题题解(简单篇)_第7张图片
empId 是这张表单的主关键字
输出示例:

LeetCode会员SQL题题解(简单篇)_第8张图片

查询代码:

MySQL:

select name,bonus from employee left join bonus using(empid) where bonus<1000 or bonus is null

SQL Server:

select t1.name,t2.bonus from employee as t1 left join bonus as t2 on t1.empid=t2.empid 
where bonus<1000 or bonus is null

586. 订单最多的客户

SQL架构:

Create table orders (order_number int, 
customer_number int, 
order_date date, 
required_date date, 
shipped_date date, 
status char(15), 
comment char(200), 
key(order_number)
);

Truncate table orders;
insert into orders (order_number, customer_number) values ('1', '1');
insert into orders (order_number, customer_number) values ('2', '2');
insert into orders (order_number, customer_number) values ('3', '3');
insert into orders (order_number, customer_number) values ('4', '3');

在表 order 中找到订单数最多客户对应的 customer_number 。

数据保证订单数最多的顾客恰好只有一位。

表 orders 定义如下:
LeetCode会员SQL题题解(简单篇)_第9张图片

样例输入:

LeetCode会员SQL题题解(简单篇)_第10张图片

样例输出:

解释

customer_number 为 '3' 的顾客有两个订单,比顾客 '1' 或者 '2' 都要多,因为他们只有一个订单
所以结果是该顾客的 customer_number ,也就是 3 。

查询代码:

MySQL:

select customer_number from orders group by customer_number
order by count(order_number) desc limit 1

SQL Server:

select top 1 customer_number from orders group by customer_number
order by count(*) desc

从此题应注意的是count函数可以用在order by子句中。

597. 好友申请 I :总体通过率

SQL架构:

Create table friend_request ( sender_id INT NOT NULL, send_to_id INT NULL, request_date DATE NULL);
Create table request_accepted ( requester_id INT NOT NULL, accepter_id INT NULL, accept_date DATE NULL);

Truncate table friend_request;

insert into friend_request (sender_id, send_to_id, request_date) values ('1', '2', '2016/06/01');
insert into friend_request (sender_id, send_to_id, request_date) values ('1', '3', '2016/06/01');
insert into friend_request (sender_id, send_to_id, request_date) values ('1', '4', '2016/06/01');
insert into friend_request (sender_id, send_to_id, request_date) values ('2', '3', '2016/06/02');
insert into friend_request (sender_id, send_to_id, request_date) values ('3', '4', '2016/06/09');

Truncate table request_accepted;

insert into request_accepted (requester_id, accepter_id, accept_date) values ('1', '2', '2016/06/03');
insert into request_accepted (requester_id, accepter_id, accept_date) values ('1', '3', '2016/06/08');
insert into request_accepted (requester_id, accepter_id, accept_date) values ('2', '3', '2016/06/08');
insert into request_accepted (requester_id, accepter_id, accept_date) values ('3', '4', '2016/06/09');
insert into request_accepted (requester_id, accepter_id, accept_date) values ('3', '4', '2016/06/10');

在 Facebook 或者 Twitter 这样的社交应用中,人们经常会发好友申请也会收到其他人的好友申请。现在给如下两个表:

表: friend_request

LeetCode会员SQL题题解(简单篇)_第11张图片

表: request_accepted

LeetCode会员SQL题题解(简单篇)_第12张图片

写一个查询语句,求出好友申请的通过率,用 2 位小数表示。通过率由接受好友申请的数目除以申请总数。

对于上面的样例数据,你的查询语句应该返回如下结果。

注意:

通过的好友申请不一定都在表 friend_request 中。在这种情况下,你只需要统计总的被通过的申请数(不管它们在不在原来的申请中),并将它除以申请总数,得到通过率。一个好友申请发送者有可能会给接受者发几条好友申请,也有可能一个好友申请会被通过好几次。这种情况下,重复的好友申请只统计一次。如果一个好友申请都没有,通过率为 0.00 。

解释: 总共有 5 个申请,其中 4 个是不重复且被通过的好友申请,所以成功率是 0.80 。

查询代码:

MySQL:

select round(
    ifnull(
    (select count(distinct requester_id ,accepter_id) from request_accepted) / 
    (select count(distinct sender_id ,send_to_id) from friend_request)
    ,0),2) as accept_rate ;

603. 连续空余座位

SQL架构:

Create table cinema (seat_id int primary key auto_increment, free bool);
Truncate table cinema;
insert into cinema (seat_id, free) values ('1', '1');
insert into cinema (seat_id, free) values ('2', '0');
insert into cinema (seat_id, free) values ('3', '1');
insert into cinema (seat_id, free) values ('4', '1');
insert into cinema (seat_id, free) values ('5', '1');

几个朋友来到电影院的售票处,准备预约连续空余座位。

你能利用表 cinema ,帮他们写一个查询语句,获取所有空余座位,并将它们按照 seat_id 排序后返回吗?

LeetCode会员SQL题题解(简单篇)_第13张图片

对于如上样例,你的查询语句应该返回如下结果。


注意:

seat_id 字段是一个自增的整数,free 字段是布尔类型('1' 表示空余, '0' 表示已被占据)。
连续空余座位的定义是大于等于 2 个连续空余的座位。

查询代码:

MySQL和SQL Server均适用:

select distinct(c1.seat_id) from cinema as c1,cinema as c2
where c1.free=1 and c2.free=1 and abs(c1.seat_id-c2.seat_id)=1
order by seat_id

607. 销售员

SQL架构:

Create table salesperson (sales_id int, name varchar(255), salary int,commission_rate int, hire_date varchar(255));
Create table company (com_id int, name varchar(255), city varchar(255));
Create table orders (order_id int, order_date varchar(255), com_id int, sales_id int, amount int);

Truncate table salesperson;

insert into salesperson (sales_id, name, salary, commission_rate, hire_date) values ('1', 'John', '100000', '6', '4/1/2006');
insert into salesperson (sales_id, name, salary, commission_rate, hire_date) values ('2', 'Amy', '12000', '5', '5/1/2010');
insert into salesperson (sales_id, name, salary, commission_rate, hire_date) values ('3', 'Mark', '65000', '12', '12/25/2008');
insert into salesperson (sales_id, name, salary, commission_rate, hire_date) values ('4', 'Pam', '25000', '25', '1/1/2005');
insert into salesperson (sales_id, name, salary, commission_rate, hire_date) values ('5', 'Alex', '5000', '10', '2/3/2007');

Truncate table company;

insert into company (com_id, name, city) values ('1', 'RED', 'Boston');
insert into company (com_id, name, city) values ('2', 'ORANGE', 'New York');
insert into company (com_id, name, city) values ('3', 'YELLOW', 'Boston');
insert into company (com_id, name, city) values ('4', 'GREEN', 'Austin');

Truncate table orders;

insert into orders (order_id, order_date, com_id, sales_id, amount) values ('1', '1/1/2014', '3', '4', '10000');
insert into orders (order_id, order_date, com_id, sales_id, amount) values ('2', '2/1/2014', '4', '5', '5000');
insert into orders (order_id, order_date, com_id, sales_id, amount) values ('3', '3/1/2014', '1', '1', '50000');
insert into orders (order_id, order_date, com_id, sales_id, amount) values ('4', '4/1/2014', '1', '4', '25000');

给定 3 个表: salesperson, company, orders。
输出所有表 salesperson 中,没有向公司 'RED' 销售任何东西的销售员。

解释:
输入

表: salesperson

LeetCode会员SQL题题解(简单篇)_第14张图片
表 salesperson 存储了所有销售员的信息。每个销售员都有一个销售员编号 sales_id 和他的名字 name 。

表: company

LeetCode会员SQL题题解(简单篇)_第15张图片
表 company 存储了所有公司的信息。每个公司都有一个公司编号 com_id 和它的名字 name 。

表: orders

LeetCode会员SQL题题解(简单篇)_第16张图片
表 orders 存储了所有的销售数据,包括销售员编号 sales_id 和公司编号 com_id 。

输出


解释:

根据表 orders 中的订单 '3' 和 '4' ,容易看出只有 'John' 和 'Pam' 两个销售员曾经向公司 'RED' 销售过。

所以我们需要输出表 salesperson 中所有其他人的名字。

查询代码:

MySQL和SQL Server均适用:

select name from salesperson where sales_id not in (select sales_id from orders where
com_id = (select com_id from company where name='RED'))

610. 判断三角形

SQL架构:

Create table triangle (x int, y int, z int);
Truncate table triangle;
insert into triangle (x, y, z) values ('13', '15', '30');
insert into triangle (x, y, z) values ('10', '20', '15');

一个小学生 Tim 的作业是判断三条线段是否能形成一个三角形。

然而,这个作业非常繁重,因为有几百组线段需要判断。

假设表 triangle 保存了所有三条线段的三元组 x, y, z ,你能帮 Tim 写一个查询语句,来判断每个三元组是否可以组成一个三角形吗?


对于如上样例数据,你的查询语句应该返回如下结果:

查询代码:

MySQL:

select x,y,z,if((x+y>z) and (x+z)>y and (y+z>x),'Yes','No') as triangle from triangle

SQL Server:

select x,y,z,(case when (x+y>z) and (x+z>y) and (y+z>x)
then 'Yes' else 'No' end) as triangle from triangle

此题要考虑的地方在于满足什么条件的三条线段可以组成一个三角形。实际上,以下两个条件只要满足其中之一即可:
任意两边之和大于第三边或者是任意两边之差小于第三边,这两个条件是等价的。

613. 直线上的最近距离

SQL架构:

CREATE TABLE point (x INT NOT NULL);
Truncate table point;
insert into point (x) values ('-1');
insert into point (x) values ('0');
insert into point (x) values ('2');

表 point 保存了一些点在 x 轴上的坐标,这些坐标都是整数。

写一个查询语句,找到这些点中最近两个点之间的距离。

最近距离显然是 '1' ,是点 '-1' 和 '0' 之间的距离。所以输出应该如下:

注意:每个点都与其他点坐标不同,表 table 不会有重复坐标出现。

查询代码:

MySQL和SQL Server均适用:

select min(abs(p1.x-p2.x)) as shortest from point as p1,point as p2
where p1.x!=p2.x

619. 只出现一次的最大数字

SQL架构:

Create table my_numbers (num int);
Truncate table my_numbers;
insert into my_numbers (num) values ('8');
insert into my_numbers (num) values ('8');
insert into my_numbers (num) values ('3');
insert into my_numbers (num) values ('3');
insert into my_numbers (num) values ('1');
insert into my_numbers (num) values ('4');
insert into my_numbers (num) values ('5');
insert into my_numbers (num) values ('6');

表 my_numbers 的 num 字段包含很多数字,其中包括很多重复的数字。

你能写一个 SQL 查询语句,找到只出现过一次的数字中,最大的一个数字吗?


对于上面给出的样例数据,你的查询语句应该返回如下结果:


注意:

如果没有只出现一次的数字,输出 null 。

查询代码:

MySQL:

select max(num) as num from (select num,count(num) as numbers from my_numbers group by num having numbers=1) as temp

SQL Server:

select max(num) as num from (select num,count(num) over(partition by num) as numbers from my_numbers) as temp where numbers=1

1050. 合作过至少三次的演员和导演

SQL架构:

Create table ActorDirector (
actor_id int, 
director_id int, 
timestamp int
);

Truncate table ActorDirector;

insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '1', '0');
insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '1', '1');
insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '1', '2');
insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '2', '3');
insert into ActorDirector (actor_id, director_id, timestamp) values ('1', '2', '4');
insert into ActorDirector (actor_id, director_id, timestamp) values ('2', '1', '5');
insert into ActorDirector (actor_id, director_id, timestamp) values ('2', '1', '6');

ActorDirector 表:

LeetCode会员SQL题题解(简单篇)_第17张图片
timestamp 是这张表的主键.

写一条SQL查询语句获取合作过至少三次的演员和导演的 id 对 (actor_id, director_id)

示例:

ActorDirector 表:
LeetCode会员SQL题题解(简单篇)_第18张图片

Result 表:
LeetCode会员SQL题题解(简单篇)_第19张图片
唯一的 id 对是 (1, 1),他们恰好合作了 3 次。

查询代码:

MySQL和SQL Server均适用:

select actor_id,director_id from actordirector 
group by actor_id,director_id
having count(*)>=3

1076. Project Employees II

SQL架构:

Create table Project (project_id int, 
employee_id int
)engine myisam charset utf8mb4;

Create table Employee2 (employee_id int, 
name varchar(10), 
experience_years int
)engine myisam charset utf8mb4;

Truncate table Project;

insert into Project (project_id, employee_id) values ('1', '1');
insert into Project (project_id, employee_id) values ('1', '2');
insert into Project (project_id, employee_id) values ('1', '3');
insert into Project (project_id, employee_id) values ('2', '1');
insert into Project (project_id, employee_id) values ('2', '4');

Truncate table Employee2;

insert into Employee2 (employee_id, name, experience_years) values ('1', 'Khaled', '3');
insert into Employee2 (employee_id, name, experience_years) values ('2', 'Ali', '2');
insert into Employee2 (employee_id, name, experience_years) values ('3', 'John', '1');
insert into Employee2 (employee_id, name, experience_years) values ('4', 'Doe', '2');

Table: Project

LeetCode会员SQL题题解(简单篇)_第20张图片
(project_id, employee_id) is the primary key of this table.
employee_id is a foreign key to Employee table.
Table: Employee

LeetCode会员SQL题题解(简单篇)_第21张图片
employee_id is the primary key of this table.

Write an SQL query that reports all the projects that have the most employees.

The query result format is in the following example:

Project table:
LeetCode会员SQL题题解(简单篇)_第22张图片

Employee table:
LeetCode会员SQL题题解(简单篇)_第23张图片

Result table:

The first project has 3 employees while the second one has 2.

查询代码:

MySQL:

select project_id
from project
group by project_id
having
count(*)=(select count(*) from project group by project_id order by
         count(*) desc limit 1)

SQL Server:

select project_id
from project
group by project_id
having
count(*)=(select top 1 count(*) from project group by project_id order by
         count(*) desc)

1082. Sales Analysis I

SQL架构:

Table: Product

LeetCode会员SQL题题解(简单篇)_第24张图片
product_id is the primary key of this table.
Table: Sales

LeetCode会员SQL题题解(简单篇)_第25张图片
This table has no primary key, it can have repeated rows.
product_id is a foreign key to Product table.

Write an SQL query that reports the best seller by total sales price, If there is a tie, report them all.

The query result format is in the following example:

Product table:
LeetCode会员SQL题题解(简单篇)_第26张图片

Sales table:
LeetCode会员SQL题题解(简单篇)_第27张图片

Result table:
LeetCode会员SQL题题解(简单篇)_第28张图片
Both sellers with id 1 and 3 sold products with the most total price of 2800.

查询代码:

MySQL1:

select seller_id from sales group by seller_id
having sum(price)=(select max(total_price) from (select sum(price) as total_price from
sales group by seller_id) as temp)

MySQL2:

select seller_id from sales group by seller_id
having sum(price)>=all(select sum(price) from sales group by seller_id )

MySQL3:

select seller_id from sales group by seller_id
having sum(price)=(select sum(price) from sales group by seller_id order by sum(price) desc limit 1)

SQL Server1:

select seller_id from sales group by seller_id
having sum(price)>=all(select sum(price) from sales group by seller_id)

SQL Server2:

select seller_id from sales group by seller_id
having sum(price)=(select top 1 sum(price) from sales group by seller_id order by sum(price) desc)

1083. Sales Analysis II

表结构与1083. Sales Analysis I相同。

Write an SQL query that reports the buyers who have bought S8 but not iPhone. Note that S8 and iPhone are products present in the Product table.

The query result format is in the following example:

Product table:
LeetCode会员SQL题题解(简单篇)_第29张图片

Sales table:
LeetCode会员SQL题题解(简单篇)_第30张图片

Result table:

The buyer with id 1 bought an S8 but didn't buy an iPhone. The buyer with id 3 bought both.

查询代码:

MySQL和SQL Server均适用:

select distinct buyer_id from sales as s left join product as p on s.product_id=p.product_id 
where p.product_name='S8' and buyer_id not in 
(select buyer_id from sales as s left join product as p on s.product_id=p.product_id where product_name ='iPhone')

1084. Sales Analysis III

表结构与1083. Sales Analysis I相同。

Write an SQL query that reports the products that were only sold in spring 2019. That is, between 2019-01-01 and 2019-03-31 inclusive.

The query result format is in the following example:

Product table:
LeetCode会员SQL题题解(简单篇)_第31张图片

Sales table:
LeetCode会员SQL题题解(简单篇)_第32张图片

Result table:

The product with id 1 was only sold in spring 2019 while the other two were sold after.

查询代码:

MySQL和SQL Server均适用:

select 
    b.product_id,b.product_name
from
(
    select 
        product_id
    from 
        sales
    group by 
        product_id
    having
        max(sale_date)<='2019-03-31' and min(sale_date)>='2019-01-01'
) a
left join
     product b
on a.product_id=b.product_id

 

你可能感兴趣的:(MySQL,SQL,Server)