目錄
第一性原理出發思考 ——我們為什么需要聚合函數?
什么是聚合函數??
常見聚合函數 + 實例講解?
?🔸 1. COUNT() —— 計數
?🔸 2. MAX() / MIN() —— 最大 / 最小值
🔸 3. SUM() —— 求和?
🔸 4. AVG() —— 平均值?
?GROUP BY
GROUP BY 是什么??
執行邏輯?
?GROUP BY 的重要規則
HAVING
為什么還要 HAVING??
HAVING 是什么??
實例講解?
HAVING 和 WHERE 的區別?
思維圖:GROUP BY + HAVING 工作流程?
第一性原理出發思考 ——我們為什么需要聚合函數?
在數據庫中,查詢的本質是從一堆數據中“找出我們需要的信息”。有時候我們不僅想看到“每一行”,而是想對一整列進行“匯總”,比如:
-
一共預訂了多少場電影?
-
哪個用戶最愛看電影?
-
每部電影平均有多少人觀看?
這個時候,我們就需要——聚合函數。
什么是聚合函數??
聚合函數是 MySQL 中用于對一整列的數據進行統計、計算或匯總的函數。它不是作用于“某一行”,而是作用于“一列”或“一組”數據。?
常見聚合函數 + 實例講解?
我們來建一個簡單的工資表 employees,字段如下:?
CREATE TABLE employees (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50),salary INT
);
插入一些數據:?
INSERT INTO employees (name, salary) VALUES
('Alice', 5000),
('Bob', 6000),
('Charlie', 5500),
('Diana', 7000),
('Eve', 6500),
('Frank', 5200);
?🔸 1. COUNT()
—— 計數
SELECT COUNT(*) FROM employees;
?我們給數據庫一個表,它掃描所有行,每遇到一行就 +1
,最后告訴你一共有幾行數據。
最后返回 6
SELECT COUNT(salary) FROM employees;
?與 COUNT(*)
類似,但如果有 NULL
工資的員工,不計入。
?🔸 2. MAX()
/ MIN()
—— 最大 / 最小值
SELECT MAX(salary), MIN(salary) FROM employees;
?數據庫掃描每一個值,記錄當前最大/最小值,直到最后一行。
最后返回:MAX: 7000, MIN: 5000?
🔸 3. SUM()
—— 求和?
SELECT SUM(salary) FROM employees;
?我們把這一列的值都加起來,輸出總和。適合處理“總銷售額”、“總時長”等問題。
最后返回:5000 + 6000 + 5500 + 7000 + 6500 + 5200 = 35,200
?
🔸 4. AVG()
—— 平均值?
SELECT AVG(salary) FROM employees;
?就是 SUM(salary) / COUNT(salary)
,把總量除以人數,得到“人均”指標。
最后返回:35200 / 6 = 5866.67?
你還可以這樣玩:?
-- 所有工資加 500 后的平均值是多少?
SELECT AVG(salary + 500) FROM employees;-- 平均名字長度(字符串函數 + 聚合函數)
SELECT AVG(CHAR_LENGTH(name)) FROM employees;
?GROUP BY
我們之前講的聚合函數是對“一整列”做統計,但很多時候,我們想知道:?
各個部門的平均工資分別是多少??
這就需要把“整張表”按部門拆成若干小組,每一組內部再用聚合函數統計。?
💡 這時候,我們就需要 GROUP BY
。?
GROUP BY 是什么??
GROUP BY
是 SQL 中的“分組器”
它把一張大表,按某個字段(或字段組合)劃分成一組組數據,然后對每組單獨使用聚合函數。?
執行邏輯?
🎯 目標:統計各個部門的平均工資?
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;
這條 SQL 的背后邏輯是這樣的:
-
掃描整張表
-
按
department
字段的值,把表劃分為若干組:-
HR: [Alice, Charlie, Frank]
-
IT: [Bob, Diana]
-
Finance: [Eve]
-
-
對每組單獨執行
AVG(salary)
-
輸出每組的
department
和對應的avg_salary
執行結果:
department | avg_salary |
---|---|
HR | 5233.33 |
IT | 6500.00 |
Finance | 6500.00 |
?GROUP BY 的重要規則
規則 | 說明 |
---|---|
SELECT 中非聚合字段必須出現在 GROUP BY 中 | 除非是聚合函數計算的,否則 SELECT 中的字段必須被 GROUP BY |
GROUP BY 后面可以接多個字段 | 表示按多個維度進行分組 |
整張表 → 按字段值分組 → 每組做聚合 → 輸出每組統計結果
HAVING
為什么還要 HAVING
??
我們已經知道:每個部門的平均工資。但問題來了:?
?“只想要平均工資大于 6000 的部門”怎么辦??
你可能第一反應是:?
SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 6000 -- 🚫 錯誤用法
GROUP BY department;
?? 錯誤!
因為 WHERE
是在分組之前起作用的,根本沒法識別 AVG(salary)
這種“分組后的值”。
HAVING 是什么??
HAVING
是用來 過濾分組后的結果 的
它和 WHERE
類似,但發生在 GROUP BY
之后?
實例講解?
🎯 問題:找出平均工資高于 6000 的部門?
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 6000;
🔍 數據回顧(之前的平均工資):
department | avg_salary |
---|---|
HR | 5233.33 |
IT | 6500.00 |
Finance | 6500.00 |
📌 這條 SQL 會返回:
department | avg_salary |
---|---|
IT | 6500.00 |
Finance | 6500.00 |
因為只有這兩個部門的平均工資大于 6000。
🔹 統計每個部門人數大于 2 的部門:
SELECT department, COUNT(*) AS num_employees
FROM employees
GROUP BY department
HAVING COUNT(*) > 2;
🔹 平均工資等于最大工資的部門
SELECT department, AVG(salary), MAX(salary) FROM employees
GROUP BY department
HAVING AVG(salary) = MAX(salary);
?使用別名:
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING avg_salary > 6000; -- ? 正確用法
HAVING 和 WHERE 的區別?
語句部分 | 用途 | 作用順序(誰先執行) |
---|---|---|
WHERE | 篩選原始數據 | 在分組之前執行 |
HAVING | 篩選分組結果 | 在分組之后執行 |
?WHERE 是篩選行,HAVING 是篩選組。
WHERE 是先手,HAVING 是后手。
思維圖:GROUP BY + HAVING 工作流程?
原始表↓ (WHERE)
過濾掉不滿足條件的行↓ (GROUP BY)
按照字段分組↓ (聚合函數)
計算每組的結果↓ (HAVING)
篩選掉不滿足條件的組↓ (SELECT)
最終展示結果