首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 無 GROUP BY 直接用 HAVING 的陷阱:MIN/MAX 取值邏輯與 GROUP BY NULL 等價 LIMIT 1

     編輯:MySQL 綜合教學

現象複現

表 t2(id PK, a),數據:(1,10)、(3,1)。

SELECT * FROM t2 HAVING id = MIN(id);  -- 返回 id=1
SELECT * FROM t2 HAVING id = MAX(id);  -- 空結果!

同理 HAVING a = MAX(a) 返回 a=10,HAVING a = MIN(a) 卻空結果。為什麼?

根因揭秘:MySQL 內部重寫為 GROUP BY NULL

標準 SQL 要求 HAVING 伴隨 GROUP BY。MySQL 為兼容單獨 HAVING,隱式重寫:

SELECT * FROM t2 HAVING id = MIN(id)
-- 內部等價於
SELECT * FROM t2 GROUP BY NULL HAVING id = MIN(id);

GROUP BY NULL 的行為 = LIMIT 1

SELECT * FROM t2 GROUP BY NULL;  -- 只返回第一行 (1,10)

分組後**僅保留第一行**作為唯一分組。

聚合函數取值範圍:全表 vs 分組內

關鍵點:**MIN/MAX 計算的是全表所有行的極值,而非分組內(此處分組內僅有一行)。**

SELECT MAX(a), MIN(a), MAX(id), MIN(id) FROM t2 GROUP BY NULL;
+--------+--------+---------+---------+
| MAX(a) | MIN(a) | MAX(id) | MIN(id) |
+--------+--------+---------+---------+
| 10     | 1      | 3       | 1       |
+--------+--------+---------+---------+

邏輯推演

  • HAVING id = MIN(id) → HAVING id = 1 → 分組內第一行 id=1 滿足 → **返回該行**。
  • HAVING id = MAX(id) → HAVING id = 3 → 分組內第一行 id=1 不滿足 → **空結果**。
  • HAVING a = MAX(a) → HAVING a = 10 → 分組內第一行 a=10 滿足 → **返回**。
  • HAVING a = MIN(a) → HAVING a = 1 → 分組內第一行 a=10 不滿足 → **空結果**。

正確做法對比

-- 取最小 id 的完整行
SELECT * FROM t2 ORDER BY id ASC LIMIT 1;
-- 取最大 a 的完整行
SELECT * FROM t2 ORDER BY a DESC LIMIT 1;
  1. 開啟 sql_mode=ONLY_FULL_GROUP_BY,MySQL 5.7.5+ 預設開啟,會直接報錯攔截此類寫法。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved