簡體   English   中英

當 select 列不是聚合 function 也不在 group by 子句中時不會出現錯誤

[英]Not getting an error when select a column that is not an aggregate function nor in the group by clause

這是來自 leetcode 的問題:

表:用戶

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| name          | varchar |
+---------------+---------+

id 是該表的主鍵。 name 是用戶的名稱。

表:游樂設施

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| user_id       | int     |
| distance      | int     |
+---------------+---------+

id 是該表的主鍵。 user_id 是行進距離“distance”的用戶的 id。

編寫一個 SQL 查詢來報告每個用戶走過的距離。

返回按 travelled_distance 降序排列的結果表,如果兩個或兩個以上的用戶行駛距離相同,則按姓名升序排列。

查詢結果格式如下例。

示例 1:

輸入:用戶表:

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

游樂設施表:

+------+----------+----------+
| 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      |
+------+----------+----------+

Output:

+----------+--------------------+
| 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這個列既不是聚合function也不在group by子句中,在使用group by子句的時候是需要的。 為什么這里沒有報錯? 上網查了下,MySQL的某些版本仍然可以運行這個場景不報錯。 有人可以為我澄清一下嗎? (PS 使用group by u.id 的原因是因為在某些測試用例中users 表中可以有重名)。

選擇 u.name 時可能沒有看到錯誤的原因有兩個,一個是好的,一個是壞的。

不好的原因是如果您沒有啟用 ONLY_FULL_GROUP_BY sql_mode; 這是默認打開的,但如果您升級了在配置文件中設置了 sql_mode 的舊服務器,或者選擇設置 sql_mode,則可能不會。 您可以執行select @@SESSION.sql_mode以查看它是否在您當前的 session 中啟用。如果是這種情況,除非您有很多現有查詢需要更新,否則您應該啟用 ONLY_FULL_GROUP_BY。 然后您需要修改此查詢(將 u.name 添加到 group by 列表中,如果 u.id 是主鍵,這應該是無害的,或者選擇 ANY_VALUE(u.name) 或 MAX(u.name) 或喜歡。

很好的理由是,如果您使用的是最新的 mysql 版本並且 u.id 是唯一鍵或主鍵; 那么,由於您是按 u.id 分組的,因此只能有一個 u.name 值,並且所選擇的內容沒有歧義。 這被稱為 u.name “功能上依賴於”u.id,並且在當前的 mysql 版本中是允許的。 (在mariadb還不允許,見https://jira.mariadb.org/browse/MDEV-11588。

您可以MAX u.name 或將其添加到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; 
名稱 旅行距離
貓王 450
450
鮑勃 317
喬納森 312
亞歷克斯 222
愛麗絲 120
唐納德 0
select
    MAX(u.name) 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, name asc; 
名稱 旅行距離
貓王 450
450
鮑勃 317
喬納森 312
亞歷克斯 222
愛麗絲 120
唐納德 0

小提琴

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM