LeetCode #排名靠前的旅行者

170 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第41天,点击查看活动详情

一、题目

表: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。

二、解题思路

创建数据表

根据题意创建数据表并填充数据

CREATE TABLE IF NOT EXISTS Users (id INT, NAME VARCHAR(30));
CREATE TABLE IF NOT EXISTS Rides (id INT, user_id INT, distance INT);

INSERT INTO Users VALUES
(1, 'Alice'),
(2, 'Bob'),
(3, 'Alex'),
(4, 'Donald'),
(7, 'Lee'),
(13, 'Jonathan'),
(19, 'Elvis');

INSERT INTO Rides VALUES
(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);

解题

  • 根据题意,本题要计算每个用户的旅行距离,那么由此可以根据用户id分组
  • 之后计算用户的旅行距离,这里的距离使用sum计算,这时有一个问题,当用户没有出门的话,距离设置为0,这里可以使用if或者ifnull都可以
  • 两张表通过左连接查询,是因为左连接查询遍历了所有的用户表并查询符合条件的距离表,可以设置假名方法使用
  • 根据题意,要以距离降序排列,同时如果距离相同则以名字升序排列
  • 最后执行语句得到结果
SELECT u.name, IF(SUM(distance),SUM(distance),0) travelled_distance
FROM Users u
LEFT JOIN Rides r
ON u.id = r.user_id
GROUP BY r.user_id
ORDER BY travelled_distance DESC,u.name ASC;

SELECT u.name, IFNULL(SUM(distance),0) travelled_distance
FROM Users u
LEFT JOIN Rides r
ON u.id = r.user_id
GROUP BY r.user_id
ORDER BY travelled_distance DESC,u.name ASC;
  • 显示结果

image.png

三、测试结果

if+sum

image.png

ifnull+sum

image.png

四、总结

  • 这里主要了解使用左连接还是右连接,因为要遍历所有用户数据,因此是左连接
  • 对空数据的处理,可以使用ifnull 也可以if或者其他的
  • 分组,要明白在这道题中是以用户为基准的,所有应该是用户id,但这里的应该是距离的用户id,因为这里计算的是距离表的距离
  • 排序,这里注意排序有两种条件,一种是距离,一种是名字