数据库每日一题---第19天:排名靠前的旅行者

193 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情

一、问题描述

Users

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| name          | varchar |
+---------------+---------+
id 是该表单主键。
name 是用户名字。

Rides

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| user_id       | int     |
| distance      | int     |
+---------------+---------+
id 是该表单主键。
user_id 是本次行程的用户的 id, 而该用户此次行程距离为 distance 。

写一段 SQL , 报告每个用户的旅行距离。

返回的结果表单,以 travelled_distance 降序排列 ,如果有两个或者更多的用户旅行了相同的距离, 那么再以 name 升序排列 。

查询结果格式如下例所示。

题目链接排名靠前的旅行者

二、题目要求

样例

Users 表:
+------+-----------+
| id   | name      |
+------+-----------+
| 1    | Alice     |
| 2    | Bob       |
| 3    | Alex      |
| 4    | Donald    |
| 7    | Lee       |
| 13   | Jonathan  |
| 19   | Elvis     |
+------+-----------+

Rides 表:
+------+----------+----------+
| id   | user_id  | distance |
+------+----------+----------+
| 1    | 1        | 120      |
| 2    | 2        | 317      |
| 3    | 3        | 222      |
| 4    | 7        | 100      |
| 5    | 13       | 312      |
| 6    | 19       | 50       |
| 7    | 7        | 120      |
| 8    | 19       | 400      |
| 9    | 7        | 230      |
+------+----------+----------+

Result 表:
+----------+--------------------+
| name     | travelled_distance |
+----------+--------------------+
| Elvis    | 450                |
| Lee      | 450                |
| Bob      | 317                |
| Jonathan | 312                |
| Alex     | 222                |
| Alice    | 120                |
| Donald   | 0                  |
+----------+--------------------+
Elvis 和 Lee 旅行了 450 英里,Elvis 是排名靠前的旅行者,因为他的名字在字母表上的排序比 Lee 更小。
Bob, Jonathan, Alex 和 Alice 只有一次行程,我们只按此次行程的全部距离对他们排序。
Donald 没有任何行程, 他的旅行距离为 0

考察

1.左外连接、聚合函数
2.建议用时10~25min

三、问题分析

这一题可以使用左外连接,常用的如下:

  • A inner join B:内连接,取交集
  • A left join B:左外连接,取A全部,B没有对应的值,则为null
  • A right join B:右外连接,取B全部,A没有对应的值,则为null
  • A full outer join B:全外连接,取并集,彼此没有对应的值为null

这一题除了用到左外连接之外,还需要注意下面几个要点:

1.输出的结果,当里程数目为0的时候,只使用sum函数输出的的结果是null,所以我们要在开始if判断里程数目是否为null

2.聚合我一开始是按照name开始聚合的,但测试用例出现了重名的现象,所以要按照id来聚合才行。

四、编码实现

select u.name, ifnull(sum(r.distance),0) as 'travelled_distance'
from Users u 
left join Rides r on u.id=r.user_id
group by user_id
order by travelled_distance desc,u.name  asc

五、测试结果

1.png

2.png

19.png