| 資料庫 | GROUP BY 規則 |
|---|---|
| Oracle | 嚴格模式:SELECT 列表中未出現在 GROUP BY 的欄位,必須套用聚合函數(MAX、MIN、COUNT 等),否則報錯 ORA-00979。 |
| MySQL (預設 sql_mode) | 寬鬆模式:允許 SELECT 非聚合欄位,隨機返回該分組內任意一行的值(通常是物理存儲順序的第一行)。 |
假設表 actor 與 actor_info 通過 actor_id 關聯,按 first_name 分組。
SELECT actor.actor_id, actor.first_name FROM actor JOIN actor_info ON actor.actor_id = actor_info.actor_id GROUP BY actor.first_name;
結果:
+----------+-------------+ | actor_id | first_name | +----------+-------------+ | 71 | ADAM | | 165 | AL | | 173 | ALAN | | ... | ... |
同一 first_name 下有多個 actor_id 時,MySQL 直接取分組內第一條記錄的 actor_id,結果不可預期、不可複現。
SELECT actor.first_name, COUNT(actor.actor_id) FROM actor JOIN actor_info ON actor.actor_id = actor_info.actor_id GROUP BY actor.first_name;
結果明確:每個名字對應的演員數量。
早期版本為了兼容舊應用、提升寫法靈活性而設計。但這極易導致「開發環境正常、生產環境數據錯亂」的隱性 Bug。
-- 會話級生效 SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY'; -- 或全域永久生效(my.cnf) [mysqld] sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
開啟後,查詢 1 將直接報錯:ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause...,強迫開發者寫出標準、可移植的 SQL。
ONLY_FULL_GROUP_BY,避免跨資料庫遷移或版本升級時出現語義偏差。