以下是leetcode的问题:
表:用户
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| id | int |
| name | varchar |
+---------------+---------+
id是该表的主键。name是用户的名称。
表:Rides
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| id | int |
| user_id | int |
| distance | int |
+---------------+---------+
id是该表的主键。user_id是行进了距离"1"的用户的id;距离";。
编写一个SQL查询来报告每个用户所走的距离。
返回按travelled_tdistance降序排列的结果表,如果两个或多个用户行驶了相同的距离,则按他们的姓名升序排列。
查询结果格式如下例所示。
示例1:
输入:用户表:
+------+-----------+
| 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 |
+------+----------+----------+
输出:
+----------+--------------------+
| name | travelled_distance |
+----------+--------------------+
| Elvis | 450 |
| Lee | 450 |
| Bob | 317 |
| Jonathan | 312 |
| Alex | 222 |
| Alice | 120 |
| Donald | 0 |
+----------+--------------------+
说明:埃尔维斯和李旅行了450英里,埃尔维斯是最热门的旅行者,因为他的名字按字母顺序比李小。Bob、Jonathan、Alex和Alice只有一次骑行,我们只按骑行的总距离排序。唐纳德没有乘坐任何交通工具,他行驶的距离是0。
以下是我的MySQL查询:
select
u.name,
coalesce(sum(r.distance), 0) as travelled_distance
from users u
left join rides r on u.id = r.user_id
group by u.id
order by travelled_distance desc, u.name asc;
我已成功运行此查询。但我发现u.name列既不是聚合函数,也不是groupby子句中的列,这在使用groupby子句时是必需的。为什么这里没有错误?我在网上搜索了一下,发现MySQL的某些版本仍然可以运行这种场景而不会出错。有人能帮我澄清一下吗?(附言:使用groupbyu.id的原因是,在某些测试用例中,users表中可能存在重复的名称)。
您可以将u.nameMAX
或添加到GROUP By
select
u.name,
coalesce(sum(r.distance), 0) as travelled_distance
from users u
left join rides r on u.id = r.user_id
group by u.id,u.name
order by travelled_distance desc, u.name asc;
name | travelled_termance |
---|---|
Elvis | 450 |
Lee | 450 |
Bob | 317 |
Jonathan | 312 |
Alex | 222 |
Alice | 120 |
Donald | 0 |
选择u.name时可能没有看到错误的原因有两个,一个好,一个坏。
坏的原因可能是您没有启用ONLY_FULL_GROUP_BY sql_mode;这在默认情况下是启用的,但如果您升级了在配置文件中设置了sql_mode的旧服务器,或者选择设置sql_mode,则可能不会。您可以执行select @@SESSION.sql_mode
以查看它是否在当前会话中启用。如果是这种情况,除非您有很多现有查询需要更新,否则您应该启用ONLY_FULL_GROUP _BY。然后,您将需要修改此查询(或者将u.name添加到按列表分组,如果u.id是主键,则这应该是无害的,或者选择ANY_VALUE(u.name)或MAX(u.name)等。
最好的理由是,如果您使用的是最新的mysql版本,并且u.id是唯一的或主键;然后,由于您是按u.id进行分组的,因此只能有一个u.name值,并且所选内容没有歧义。这被称为u.name;"功能相关";在u.id上,并且在当前的mysql版本中是允许的。(马里亚德布还不允许这样做,请参阅https://jira.mariadb.org/browse/MDEV-11588.)