[英]SQL: Must appear in the GROUP BY clause or be used in an aggregate function
[英]selected items don't have to appear in the GROUP BY clause or be used in an aggregate function
我被教導並聽說在 sql/mysql 中, select
子句中的項目必須出現在 GROUP BY 子句中或在聚合 function 中使用,如這里
但是,下面的示例可能改變了我的想法。
兩張表:學生(sid是關鍵)
sid | name | email
========================
99901| mike | mike@a.edu
99902| jane | jane@b.edu
99903| peter| pete@b.edu
Take(sid+oid一起是key,oid代表offering id)
sid | oid| grade
==================
99901| 1 | 100
99901| 2 | 30
99901| 3 | 40
99902| 4 | 100
99902| 5 | 100
99902| 6 | 40
99903| 6 | 95
問題:我想找到每個上過至少 2 門課程的學生的 sid、姓名和平均成績。
答案:
select s.sid, name, avg(grade) as average
from Student as s, Took as t
where s.sid = t.sid
group by s.sid
having count(*) >= 2;
結果:
sid | name | avgerage
=======================
99901| mike | 56.6667
99902| jane | 80.0000
基於必須出現在 GROUP BY 子句中或在聚合 function 中使用,查詢應該是不正確的,因為name
既不在組子句中,也不在聚合 function 中。
我看了一些帖子, 我的理解是,雖然name
既不在組子句中,也不是聚合 function,我們按sid
分組,這是鍵,每個sid
只對應一個name
,所以它不會返回多個選項sql 不知道返回哪一個。 為了確認我的理解,如果我 select 多一列email
,它仍然可以; 但是如果我 select oid
,它會給出錯誤,因為每個sid
對應多個oid
。
有人可以糾正我的理解,如果它是錯誤的,或者更詳細地說明這個陳述: must appear in the GROUP BY clause or be used in an aggregate function
謝謝。
第一次編輯:
順便說一句,我在 MySQL 8.0.17 中進行了測試
第二次編輯:
當您閱讀下面的答案/評論時,只是有用鏈接的摘要。
首先,您應該使用正確的、顯式的JOIN
語法:
select s.sid, s.name, avg(grade) as average
from Student s join
Took t
on s.sid = t.sid
group by s.sid
having count(*) >= 2;
這將起作用,因為稱為功能依賴項。 基本上,這是標准的一部分:如果您group by
,那么您可以包含該表中的任何列。
這是有關該主題的文檔。
也就是說,因為數據庫知道s.sid
是唯一的,所以使用其他列是安全的。 這是標准的一部分。 我知道的唯一支持這一點的其他通用數據庫是 Postgres。
你被教對了。
根據 SQL 標准,當您使用GROUP BY
時, SELECT
子句中可能出現的列分為三類:
GROUP BY
子句中包含的列。 在這種情況下,您有s.sid
。avg(grade)
。s.sid
是表的 PK,因此您可以包含s.name
而不聚合它。所以一切都很好。
但是,您應該知道 MySQL 5.7.4 及更早版本確實允許您以非聚合形式包含其他列。 這是我個人認為容易出錯的 MySQL 的錯誤/功能。 如果你這樣做,MySQL 將默默地隨機選擇一個值,而不聚合它,也不會告訴你。
可以通過在 MySQL 的較新版本中使用ONLY_FULL_GROUP_BY
配置參數(正如@Shawn 在評論中指出的那樣)打開此功能,以允許運行舊/壞查詢。 不過,我會盡量避免使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.