MySQL 基础4

首先放张图,以便于自己日后查看复习,该图来自如下链接:
https://blog.youkuaiyun.com/y3329223/article/details/88084323
 内连接与外连接的介绍和区别

项目十六 分数排名 (难度:中等)

依然是昨天的分数表,实现排名功能,但是排名需要是非连续的,如下:
±------±-----+
| Score | Rank |
±------±-----+
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 3 |
| 3.65 | 4 |
| 3.65 | 4 |
| 3.50 | 6 |
±------±-----

DROP TABLE IF EXISTS Score;

CREATE TABLE Score(
Id INT,
score DECIMAL(3,2)
);

INSERT INTO Score VALUES(1,3.65);
INSERT INTO Score VALUES(2,3.50);
INSERT INTO Score VALUES(3,4.00);
INSERT INTO Score VALUES(4,3.85);
INSERT INTO Score VALUES(5,3.65);
INSERT INTO Score VALUES(6,4.00);

SELECT score,
CASE 
WHEN @pre_score = score THEN @rank_tmp
WHEN @pre_score:=score THEN @rank_tmp:=@rank_tmp+1
END AS 'rank'
FROM score,(SELECT @rank_tmp:=0,@pre_score:=NULL) tmp
ORDER BY
score.score DESC;

结果如下;
在这里插入图片描述
参考:
https://www.cnblogs.com/sunchaothu/p/10467361.html

项目十七:查询回答率最高的问题 (难度:中等)

求出survey_log表中回答率最高的问题,表格的字段有:uid, action, question_id, answer_id, q_num, timestamp
uid是用户id;action的值为:“show”, “answer”, “skip”;当action是"answer"时,answer_id不为空,相反,当action是"show"和"skip"时为空(null);q_num是问题的数字序号。
写一条sql语句找出回答率最高的问题。
举例:
输入

12345678±-----±----------±-------------±-----------±----------±-----------+| uid | action | question_id | answer_id | q_num | timestamp |±-----±----------±-------------±-----------±----------±-----------+| 5 | show | 285 | null | 1 | 123 || 5 | answer | 285 | 124124 | 1 | 124 || 5 | show | 369 | null | 2 | 125 || 5 | skip | 369 | null | 2 | 126 |±-----±----------±-------------±-----------±----------±-----------+

输出

12345±------------+| survey_log |±------------+| 285 |±------------+

说明
问题285的回答率为1/1,然而问题369的回答率是0/1,所以输出是285。
注意: 最高回答率的意思是:同一个问题出现的次数中回答的比例。

创建表:
DROP TABLE IF EXISTS survey_log;

CREATE TABLE survey_log(
uid INT, 
action VARCHAR(50), 
question_id INT, 
answer_id INT, 
q_num INT, 
timestamp INT
);
插入数据:
INSERT INTO survey_log VALUES(5, 'show', 285, NULL, 1,123);
INSERT INTO survey_log VALUES(5, 'answer', 285, 124124, 1,124);
INSERT INTO survey_log VALUES(5, 'show', 369, NULL, 2,125);
INSERT INTO survey_log VALUES(5, 'skip', 369, NULL, 2,126);

选取:
SELECT survey_log
FROM(
			SELECT t.survey_log, dense_rank() over (ORDER BY ratio DESC) as 'Rank'
			FROM(
						SELECT s.question_id as survey_log,
						(CASE
						WHEN SUM(s.action = 'answer') = 0 then 0
						else SUM(s.action = 'answer') / COUNT(*)
						END) as ratio
						FROM survey_log as s
			GROUP BY uid, question_id) as t
) as p
WHERE p.Rank = 1;

结果:
在这里插入图片描述

项目十八:各部门前3高工资的员工(难度:中等)

将项目7中的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高工资的员工功能。

DROP TABLE IF EXISTS employee;
DROP TABLE IF EXISTS department;

创建表;
CREATE TABLE Employee (
Id int, 
Name varchar(255), 
Salary int, 
DepartmentId int
);

CREATE TABLE Department (
Id int, 
Name varchar(255)
);
Truncate table Employee;

插入数据:
INSERT INTO Employee (Id, Name, Salary,DepartmentId) VALUES ('1', 'Joe', '70000', '1');
INSERT INTO Employee (Id, Name, Salary,DepartmentId) VALUES ('2', 'Henry', '80000', '2');
INSERT INTO Employee (Id, Name, Salary,DepartmentId) VALUES ('3', 'Sam', '60000', '2');
INSERT INTO Employee (Id, Name, Salary,DepartmentId) VALUES ('4', 'Max', '90000', '1');
INSERT INTO Employee (Id, Name, Salary,DepartmentId) VALUES ('1', 'Janet', '69000', '1');
INSERT INTO Employee (Id, Name, Salary,DepartmentId) VALUES ('1', 'Randy', '85000', '1');

INSERT INTO Department (Id, Name) VALUES('1', 'IT');
INSERT INTO Department (Id, Name) VALUES('2', 'Sales');

选取:
SELECT d.Name AS Department, e1.Name AS Employee, e1.Salary
FROM Employee e1 JOIN Department d ON e1.DepartmentId = d.Id
WHERE 3 > (SELECT COUNT(DISTINCT e2.Salary) FROM Employee e2
           WHERE e2.Salary > e1.Salary AND e1.DepartmentId = e2.DepartmentId);

结果:
在这里插入图片描述
参考:
https://www.cnblogs.com/an5456/p/10478949.html
https://blog.youkuaiyun.com/qq_40803710/article/details/80303072

项目十九:平面上最近距离

point_2d 表包含一个平面内一些点(超过两个)的坐标值(x,y)。
写一条查询语句求出这些点中的最短距离并保留2位小数。

xy
-1-1
00
-1-2

最短距离是1,从点(-1,-1)到点(-1,2)。所以输出结果为:

shortest
1.00

注意: 所有点的最大距离小于10000。

创建表:
DROP TABLE IF EXISTS Trips;

CREATE TABLE point_2d(
x INT,
y INT
);

插入数据:
INSERT INTO POINT_2d VALUES(-1,-1);
INSERT INTO POINT_2d VALUES(0,0);
INSERT INTO POINT_2d VALUES(-1,-2);

选取:
SELECT MIN(distance) as shortest
FROM(
			SELECT POW ((p1.x - p2.x),2) + POW((p1.y - p2.y), 2)  as distance
			FROM point_2d as p1
			INNER JOIN point_2d as p2
			ON !(p1.x = p2.x and p1.y = p2.y)
) as p;

结果:
在这里插入图片描述

项目二十:行程和用户(难度:困难)

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-01|
| 2 | 2 | 11 | 1 | cancelled_by_driver|2013-10-01|
| 3 | 3 | 12 | 6 | completed |2013-10-01|
| 4 | 4 | 13 | 6 | cancelled_by_client|2013-10-01|
| 5 | 1 | 10 | 1 | completed |2013-10-02|
| 6 | 2 | 11 | 6 | completed |2013-10-02|
| 7 | 3 | 12 | 6 | completed |2013-10-02|
| 8 | 2 | 12 | 12 | completed |2013-10-03|
| 9 | 3 | 10 | 12 | completed |2013-10-03|
| 10 | 4 | 13 | 12 | cancelled_by_driver|2013-10-03|
±—±----------±----------±--------±-------------------±---------+
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 |
±-----------±------------------+

创建表:
DROP TABLE IF EXISTS Trips;
DROP TABLE IF EXISTS Users;

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 VARCHAR(50)
);

CREATE TABLE IF NOT EXISTS Users (
Users_Id INT, 
Banned   VARCHAR(50), 
Role     ENUM('client', 'driver', 'partner')
);

插入数据:
TRUNCATE TABLE 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');

TRUNCATE TABLE Users;
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
    Request_at AS DAY,
    ROUND( SUM( CASE WHEN `Status` LIKE 'cancelled%' THEN 1 ELSE 0 END ) / COUNT( * ), 2 ) AS cancelled_rate 
FROM
    trips
    LEFT JOIN ( SELECT Users_Id, Banned FROM users ) client ON trips.Client_Id = client.Users_Id
    LEFT JOIN ( SELECT Users_Id, Banned FROM users ) driver ON trips.Driver_Id = driver.Users_Id
    WHERE client.Banned = 'NO' AND driver.Banned = 'NO'
    GROUP BY Request_at
    ORDER BY Request_at;

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值