MySQL打卡练习-4
练习一:各部门前3高工资的员工(难度:中等)
问题描述
将练习一中的 employee 表清空,重新插入以下数据(也可以复制练习一中的 employee 表,再插入第5、第6行数据):
+----+-------+--------+--------------+
| Id | Name | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1 | Joe | 70000 | 1 |
| 2 | Henry | 80000 | 2 |
| 3 | Sam | 60000 | 2 |
| 4 | Max | 90000 | 1 |
| 5 | Janet | 69000 | 1 |
| 6 | Randy | 85000 | 1 |
+----+-------+--------+--------------+
编写一个 SQL 查询,找出每个部门工资前三高的员工。例如,根据上述给定的表格,查询结果应返回:
+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT | Max | 90000 |
| IT | Randy | 85000 |
| IT | Joe | 70000 |
| Sales | Henry | 80000 |
| Sales | Sam | 60000 |
+------------+----------+--------+
此外,请考虑实现各部门前N高工资的员工功能。
解题答案
创建数据
INSERT INTO Employee
VALUES (1, "joe", 70000, 1),
(2, "Henry", 80000, 2),
(3, "Sam", 60000, 2),
(4, "Max", 90000, 1),
(5, "Janet", 69000, 1),
(6, "Randy", 85000, 1);
SELECT *
FROM Employee;
代码
SELECT Name, Department, salary
FROM (
SELECT salary,
E.Name as "Name",
D.Name as "Department",
DENSE_RANK() OVER (PARTITION BY Department_ID ORDER BY salary DESC ) as "ranking"
FROM Employee as E
LEFT JOIN Department as D
ON E.Department_ID = D.Id
) as sub
WHERE ranking <= 3
;
练习二:平面上最近距离 (难度: 困难)
问题描述
point_2d表包含一个平面内一些点(超过两个)的坐标值(x,y)。
写一条查询语句求出这些点中的最短距离并保留2位小数。
|x | y |
|----|----|
| -1 | -1 |
| 0 | 0 |
| -1 | -2 |
最短距离是1,从点(-1,-1)到点(-1,-2)。所以输出结果为:
| shortest |
1.00
+--------+
|shortest|
+--------+
|1.00 |
+--------+
**注意:**所有点的最大距离小于10000。
解题答案
创建数据
CREATE TABLE point_2d
(
x int,
y int
);
INSERT INTO point_2d
VALUES (-1, -1),
(0, 0),
(-1, -2);
代码
SELECT ROUND(min(SQRT(POW(p1.x - p2.x, 2) + POW((p1.y - p2.y), 2))), 2) as "shortest"
FROM point_2d as p1
CROSS JOIN point_2d as p2
WHERE p1.x < p2.x
or p1.y < p2.y;
练习三:行程和用户(难度:困难)
问题描述
Trips 表中存所有出租车的行程信息。每段行程有唯一键 Id,Client_Id 和 Driver_Id 是 Users 表中 Users_Id 的外键。Status 是枚举类型,枚举成员为 (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’)。
Id | Client_Id | Driver_Id | City_Id | Status | Request_at |
---|
1 | 1 | 10 | 1 | completed | 2013-10-1 | 2 | 2 | 11 | 1 | cancelled_by_driver | 2013-10-1 | 3 | 3 | 12 | 6 | completed | 2013-10-1 | 4 | 4 | 13 | 6 | cancelled_by_client | 2013-10-1 | 5 | 1 | 10 | 1 | completed | 2013-10-2 | 6 | 2 | 11 | 6 | completed | 2013-10-2 | 7 | 3 | 12 | 6 | completed | 2013-10-2 | 8 | 2 | 12 | 12 | completed | 2013-10-3 | 9 | 3 | 10 | 12 | completed | 2013-10-3 | 10 | 4 | 13 | 12 | cancelled_by_driver | 2013-10-3 |
Users 表存所有用户。每个用户有唯一键 Users_Id。Banned 表示这个用户是否被禁止,Role 则是一个表示(‘client’, ‘driver’, ‘partner’)的枚举类型。
+----------+--------+--------+
| Users_Id | Banned | Role |
+----------+--------+--------+
| 1 | No | client |
| 2 | Yes | client |
| 3 | No | client |
| 4 | No | client |
| 10 | No | driver |
| 11 | No | driver |
| 12 | No | driver |
| 13 | No | driver |
+----------+--------+--------+
写一段 SQL 语句查出2013年10月1日至2013年10月3日期间非禁止用户的取消率。基于上表,你的 SQL 语句应返回如下结果,取消率(Cancellation Rate)保留两位小数。
+------------+-------------------+
| Day | Cancellation Rate |
+------------+-------------------+
| 2013-10-01 | 0.33 |
| 2013-10-02 | 0.00 |
| 2013-10-03 | 0.50 |
+------------+-------------------+
解题答案
创建数据
CREATE TABLE IF NOT EXISTS Trips
(
Id INT,
Client_Id INT,
Driver_Id INT,
City_Id INT,
Status ENUM ("completed","cancelled_by_driver", "cancelled_by_client"),
Request_at DATE
);
TRUNCATE Trips;
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('1', '1', '10', '1', 'completed', '2013-10-01');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('2', '2', '11', '1', 'cancelled_by_driver', '2013-10-01');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('3', '3', '12', '6', 'completed', '2013-10-01');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('4', '4', '13', '6', 'cancelled_by_client', '2013-10-01');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('5', '1', '10', '1', 'completed', '2013-10-02');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('6', '2', '11', '6', 'completed', '2013-10-02');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('7', '3', '12', '6', 'completed', '2013-10-02');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('8', '2', '12', '12', 'completed', '2013-10-03');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('9', '3', '10', '12', 'completed', '2013-10-03');
insert into Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at)
values ('10', '4', '13', '12', 'cancelled_by_driver', '2013-10-03');
CREATE TABLE IF NOT EXISTS Users
(
Users_Id INT,
Banned VARCHAR(10),
Role ENUM ("client", "driver", "parter")
);
insert into Users (Users_Id, Banned, Role)
values ('1', 'No', 'client');
insert into Users (Users_Id, Banned, Role)
values ('2', 'Yes', 'client');
insert into Users (Users_Id, Banned, Role)
values ('3', 'No', 'client');
insert into Users (Users_Id, Banned, Role)
values ('4', 'No', 'client');
insert into Users (Users_Id, Banned, Role)
values ('10', 'No', 'driver');
insert into Users (Users_Id, Banned, Role)
values ('11', 'No', 'driver');
insert into Users (Users_Id, Banned, Role)
values ('12', 'No', 'driver');
insert into Users (Users_Id, Banned, Role)
values ('13', 'No', 'driver');
代码
SELECT *
FROM Trips as t
LEFT JOIN Users as u
ON u.Users_Id = t.Client_Id
WHERE Banned != "Yes" AND Request_at BETWEEN 20131001 AND 20131003;
SELECT Request_at AS "Day", AVG(Status != "completed") as 'Cancellation Rate'
FROM Trips as t
LEFT JOIN Users as u
ON u.Users_Id = t.Client_Id
WHERE Banned != "Yes" AND Request_at BETWEEN 20131001 AND 20131003
GROUP BY Request_at
ORDER BY Request_at;
|