Bootstrap

1,SQL专题训练之:力扣262.行程与用户(困难)

目录

一,原题力扣链接

二,题干

三,建表语句

四,分析

五,SQL解答

六,验证

七,知识点总结


一,原题力扣链接

. - 力扣(LeetCode)

二,题干

表:Trips

+-------------+----------+
| Column Name | Type     |
+-------------+----------+
| id          | int      |
| client_id   | int      |
| driver_id   | int      |
| city_id     | int      |
| status      | enum     |
| request_at  | varchar  |     
+-------------+----------+
id 是这张表的主键(具有唯一值的列)。
这张表中存所有出租车的行程信息。每段行程有唯一 id ,其中 client_id 和 driver_id 是 Users 表中 users_id 的外键。
status 是一个表示行程状态的枚举类型,枚举成员为(‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’) 。

表:Users

+-------------+----------+
| Column Name | Type     |
+-------------+----------+
| users_id    | int      |
| banned      | enum     |
| role        | enum     |
+-------------+----------+
users_id 是这张表的主键(具有唯一值的列)。
这张表中存所有用户,每个用户都有一个唯一的 users_id ,role 是一个表示用户身份的枚举类型,枚举成员为 (‘client’, ‘driver’, ‘partner’) 。
banned 是一个表示用户是否被禁止的枚举类型,枚举成员为 (‘Yes’, ‘No’) 。

取消率 的计算方式如下:(被司机或乘客取消的非禁止用户生成的订单数量) / (非禁止用户生成的订单总数)。

编写解决方案找出 "2013-10-01" 至 "2013-10-03" 期间非禁止用户(乘客和司机都必须未被禁止)的取消率。非禁止用户即 banned 为 No 的用户,禁止用户即 banned 为 Yes 的用户。其中取消率 Cancellation Rate 需要四舍五入保留 两位小数 。

返回结果表中的数据 无顺序要求 。

结果格式如下例所示。

示例 1:

输入: 
Trips 表:
+----+-----------+-----------+---------+---------------------+------------+
| 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   |
+----------+--------+--------+
| 1        | No     | client |
| 2        | Yes    | client |
| 3        | No     | client |
| 4        | No     | client |
| 10       | No     | driver |
| 11       | No     | driver |
| 12       | No     | driver |
| 13       | No     | driver |
+----------+--------+--------+
输出:
+------------+-------------------+
| Day        | Cancellation Rate |
+------------+-------------------+
| 2013-10-01 | 0.33              |
| 2013-10-02 | 0.00              |
| 2013-10-03 | 0.50              |
+------------+-------------------+
解释:
2013-10-01:
  - 共有 4 条请求,其中 2 条取消。
  - 然而,id=2 的请求是由禁止用户(user_id=2)发出的,所以计算时应当忽略它。
  - 因此,总共有 3 条非禁止请求参与计算,其中 1 条取消。
  - 取消率为 (1 / 3) = 0.33
2013-10-02:
  - 共有 3 条请求,其中 0 条取消。
  - 然而,id=6 的请求是由禁止用户发出的,所以计算时应当忽略它。
  - 因此,总共有 2 条非禁止请求参与计算,其中 0 条取消。
  - 取消率为 (0 / 2) = 0.00
2013-10-03:
  - 共有 3 条请求,其中 1 条取消。
  - 然而,id=8 的请求是由禁止用户发出的,所以计算时应当忽略它。
  - 因此,总共有 2 条非禁止请求参与计算,其中 1 条取消。
  - 取消率为 (1 / 2) = 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 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')

四,分析

1,表结构分析:Trips表有2个字段和Users的users_id关联.分别是司机和乘客.

2,  拼图:

3,实现以上拼图 建立连接 

Trips和Users 内连接 条件是 Trips乘客id和users表的id 相等 这个是表一;

Trips和Users 内连接 条件是 Trips用户id和users表的id  相等 这个是表二;

表一和表二  内连接 条件:是表一的Trips订单id等于表二的Trips订单sid;

4,在上图里面在去无用的字段,比如city 得到下面的图表

5,根据条件去除了 第一个条件 非禁止用户 也就是 banned必须是no的订单才有效

6,去除之后得到:

7,继续去条件,时间是 1号到3号

8,开始分组 聚合统计  以 时间分组,求不同时间的订单总数.   我们乘坐表三

9,回到上上张图,取消率 拿到被取消的订单

10,得到  这个是每天 被司机或者乘客取消的订单  每天去掉的订单总数表   我们称作为表四

11,拼接表三和表四  用内连接拼接 

12, 以每天的被去掉订单数量/每天的总订单 

得到取消率  然后在拼接上时间  最终得到

五,SQL解答

 
select z1.t_at as Day ,if(ROUND(z2.fen/z1.zong,2) is null,0.00,ROUND(z2.fen / z1.zong, 2)) as 'Cancellation Rate'
from 
(
select d1.t_at, count(d1.t_id)as zong
from (
        select
            t.id as t_id, t.client_id as t_cid, t.status as t_s, t.request_at as t_at, u.banned as u_b
        from Trips t, Users u
        where
            t.client_id = u.users_id
    ) d1, (
        select
            t1.id as t1_id, t1.driver_id as t1_cid, t1.status as t1_s, t1.request_at as t1_at, u1.banned as u1_b
        from Trips t1, Users u1
        where
            t1.driver_id = u1.users_id
    ) c1
where
    d1.t_id = c1.t1_id
    and d1.u_b = 'No' # 非禁止司机
    and c1.u1_b = 'No' #非禁止乘客
    and d1.t_at BETWEEN '2013-10-01' and '2013-10-03' #时间范围
    and c1.t1_at BETWEEN '2013-10-01' and '2013-10-03' # 时间范围
GROUP BY
    d1.t_at,
    c1.t1_at) z1 LEFT JOIN
    (
select d1.t_at, count(d1.t_id) as fen
from (
        select
            t.id as t_id, t.client_id as t_cid, t.status as t_s, t.request_at as t_at, u.banned as u_b
        from Trips t, Users u
        where
            t.client_id = u.users_id
    ) d1, (
        select
            t1.id as t1_id, t1.driver_id as t1_cid, t1.status as t1_s, t1.request_at as t1_at, u1.banned as u1_b
        from Trips t1, Users u1
        where
            t1.driver_id = u1.users_id
    ) c1
where
    d1.t_id = c1.t1_id
    and d1.u_b = 'No' # 非禁止司机
    and c1.u1_b = 'No' #非禁止乘客
    and d1.t_at BETWEEN '2013-10-01' and '2013-10-03' #时间范围
    and c1.t1_at BETWEEN '2013-10-01' and '2013-10-03' # 时间范围
    and d1.t_s in (
        'cancelled_by_driver',
        'cancelled_by_client'
    )
    and c1.t1_s in (
        'cancelled_by_driver',
        'cancelled_by_client'
    )
GROUP BY
    d1.t_at,
    c1.t1_at)z2 on z1.t_at=z2.t_at;
 

六,验证

 

七,知识点总结

  • 多表连接,反复的连接
  • 内连接和左连接
  • round函数
  • if 函数
  • if null 函数
  • 多表嵌套
  • 取别名 多表嵌套里面提取有效字段

;