Mysql

only_full_group_by 的問題

  • October 4, 2018

我試圖使用 MySQL 解決這個 HackerRank 問題,這就是我想出的:

select id, wands_property.age, min(wands.coins_needed), wands.power
from wands
join wands_property
on wands_property.code = wands.code
where wands_property.is_evil = 0
group by power, age
order by power desc, age desc;

這給了我一個編譯錯誤:

第 1 行的錯誤 1055 (42000):SELECT 列表的表達式 #1 不在 GROUP BY 子句中,並且包含在功能上不依賴於 GROUP BY 子句中的列的非聚合列“run_ctaqjwhj9bt.wands.id”;這與 sql_mode=only_full_group_by 不兼容

現在,我知道 id 有多個結果 - 這是問題的關鍵,有多個具有相同年齡和功率但價格不同的魔杖 - 但既然我已經指定我想要最低價格,我不應該得到只有最低價格的魔杖對應的id?

編輯:我用這個解決了它:

select w.id, wp.age, w.coins_needed, w.power
from wands as w
join wands_property as wp
on wp.code = w.code
where wp.is_evil = 0 and w.coins_needed = (
   select min(coins_needed)
   from wands
   join wands_property
   on wands.code = wands_property.code
   where wands.power = w.power and wands_property.age = wp.age
   group by power, age
)
order by power desc, age desc;

但我注意到一些我不太明白的事情:如果我添加

and wands.id = w.id

到最後一個 where 子句,我得到了不同價格的重複(功率和年齡)結果,而不僅僅是最低價格。這是為什麼?

直接告訴你答案是作弊,所以我只是給你一個提示——這個問題是關於一個非常非常著名的 SQL 問題,以至於它在​​ MySQL 手冊上有自己的頁面:

https://dev.mysql.com/doc/refman/5.7/en/examples.html

並且搜尋發現這種問題已經在這個網站上至少被問過十幾次了。

告訴你更多的內容將違背挑戰的精神。

我可以解釋為什麼會出錯 - 使用聚合函式時,您只能使用聚合函式選擇已聚合的欄位或其他欄位,但不能選擇非聚合欄位,因為 SQL 不知道你想要最小的一個。您想要做的是找到最小值,然後使用該值在同一行上獲取相應的值,但是您不能通過這樣一個簡單的查詢“聚合併獲取另一列的值”——一旦聚合,其他欄位“失去”。在以前的 MySQL 版本中,您的查詢是合法的,但它給出了一個“隨機/不確定”的 id 值。

您可以嘗試將列 (id) 包含在ANY_VALUE(id)其中,這將忽略此引發條件。

這是因為sql_mode=only_full_group_by. 一般它的sql_mode=traditional

引用自:https://dba.stackexchange.com/questions/202194