對應教材:第 6.1 節 本週目標:把 SQL 練到能當場手寫查詢,這是 MIS 職位的關鍵技能 每日投入:1.5 ~ 2 小時 本週產出:在 SQLite / MySQL 練完 30 題查詢
本週學習目標
- [ ] 熟練 SELECT / WHERE / ORDER BY
- [ ] 熟練 GROUP BY / 聚合函數 / HAVING
- [ ] 會 JOIN 多表查詢(INNER / LEFT / RIGHT)
- [ ] 會 INSERT / UPDATE / DELETE(且知道 WHERE 的重要)
- [ ] 理解 SQL 執行順序
- [ ] 會用子查詢(Subquery)
- [ ] 理解 NULL 的特殊行為
- [ ] 能不看資料手寫面試常考的 SQL 題
每日進度
Day 1:環境準備 + 基本查詢
- 安裝 SQLite(最輕量)或用線上 SQL 練習平台(如 SQLiteOnline、DB Fiddle)
- 建立
employees、departments兩張表並塞測試資料
-- 建表
CREATE TABLE departments (
id INTEGER PRIMARY KEY,
dept_name TEXT NOT NULL
);
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
department TEXT,
dept_id INTEGER,
salary INTEGER,
hire_date DATE,
FOREIGN KEY (dept_id) REFERENCES departments(id)
);
-- 塞測試資料
INSERT INTO departments VALUES (1, '資訊部'), (2, '業務部'), (3, '產線部'), (4, '管理部');
INSERT INTO employees VALUES
(1, '王小明', 'IT', 1, 55000, '2023-03-15'),
(2, '李小華', 'IT', 1, 48000, '2024-01-10'),
(3, '張大偉', 'Sales', 2, 42000, '2022-06-01'),
(4, '陳美麗', 'IT', 1, 62000, '2021-08-20'),
(5, '林志強', 'Production', 3, 38000, '2024-05-12'),
(6, '黃小芳', 'Sales', 2, 45000, '2023-11-03'),
(7, '吳建宏', 'Production', 3, 40000, '2022-09-18'),
(8, '趙雅琪', 'Admin', 4, 50000, '2021-03-01'),
(9, '周大鵬', 'IT', 1, 58000, '2023-07-22'),
(10, '鄭小蓮', 'Production', 3, 36000, '2024-08-01');
- 基本查詢練習:
-- 查所有欄位
SELECT * FROM employees;
-- 查特定欄位
SELECT name, salary FROM employees;
-- 篩選 + 排序
SELECT name, salary FROM employees
WHERE department = 'IT'
ORDER BY salary DESC;
-- 限制筆數
SELECT name, salary FROM employees
ORDER BY salary DESC
LIMIT 5;
Day 2:篩選與排序進階
- WHERE 條件運算子:
| 運算子 | 用途 | 範例 |
|---|---|---|
| = | 等於 | WHERE dept = 'IT' |
| <> 或 != | 不等於 | WHERE dept <> 'IT' |
| > < >= <= | 比較 | WHERE salary > 50000 |
| BETWEEN | 範圍(含頭尾) | WHERE salary BETWEEN 40000 AND 50000 |
| IN | 多值比對 | WHERE dept IN ('IT', 'Sales') |
| LIKE | 模糊比對 | WHERE name LIKE '王%' |
| IS NULL | 判斷空值 | WHERE dept_id IS NULL |
| IS NOT NULL | 判斷非空 | WHERE dept_id IS NOT NULL |
| AND / OR | 組合條件 | WHERE dept = 'IT' AND salary > 50000 |
| NOT | 否定 | WHERE NOT department = 'IT' |
- LIKE 萬用字元:
%= 任意多字元、_= 恰好一個字元 ORDER BY多欄位排序:ORDER BY department ASC, salary DESCLIMIT(MySQL/SQLite)、TOP(SQL Server)、FETCH FIRST N ROWS ONLY(Oracle/標準SQL)- NULL 的特殊行為:
- NULL 不等於任何值,包括自己(
NULL = NULL是 FALSE) - 必須用
IS NULL/IS NOT NULL判斷 - 聚合函數會忽略 NULL(除了 COUNT(*))
Day 3:聚合與分組
-- 基本聚合函數
SELECT
COUNT(*) AS 總人數,
AVG(salary) AS 平均薪資,
MAX(salary) AS 最高薪,
MIN(salary) AS 最低薪,
SUM(salary) AS 薪資總額
FROM employees;
-- 分組統計
SELECT department,
COUNT(*) AS 人數,
AVG(salary) AS 平均薪資,
MAX(salary) AS 最高薪
FROM employees
GROUP BY department;
-- HAVING 篩選分組結果
SELECT department, COUNT(*) AS 人數, AVG(salary) AS 平均薪資
FROM employees
GROUP BY department
HAVING COUNT(*) > 2;
- 釐清 WHERE(分組前篩列)vs HAVING(分組後篩組):
- WHERE:先篩選哪些「列」要進來
- GROUP BY:把篩選後的列做分組
- HAVING:對分組結果做篩選
-
範例:「各部門人數超過 2 人且排除薪水低於 35000 的員工」
sql SELECT department, COUNT(*) AS 人數 FROM employees WHERE salary >= 35000 -- 先篩掉薪水太低的(列層級) GROUP BY department HAVING COUNT(*) > 2; -- 再篩人數超過 2 的部門(組層級) -
常用聚合函數:
| 函數 | 功能 | 注意 |
|---|---|---|
| COUNT(*) | 計算列數(含 NULL) | |
| COUNT(欄位) | 計算非 NULL 的列數 | |
| SUM(欄位) | 加總 | 忽略 NULL |
| AVG(欄位) | 平均 | 忽略 NULL |
| MAX(欄位) | 最大值 | |
| MIN(欄位) | 最小值 |
Day 4:JOIN 多表關聯
-- INNER JOIN:兩邊都有才出現
SELECT e.name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.id;
-- LEFT JOIN:左表全保留,右表沒對到補 NULL
SELECT e.name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.id;
-- 實務範例:找出沒有對應部門的員工
SELECT e.name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.id
WHERE d.id IS NULL;
- JOIN 類型比較:
| JOIN 類型 | 結果 |
|---|---|
| INNER JOIN | 只保留兩邊都對到的 |
| LEFT JOIN | 左表全保留,右表沒對到補 NULL |
| RIGHT JOIN | 右表全保留,左表沒對到補 NULL |
| FULL OUTER JOIN | 兩邊全保留,沒對到的補 NULL |
| CROSS JOIN | 笛卡兒積(所有組合) |
- JOIN 技巧:
- 用別名(alias)簡化:
FROM employees e JOIN departments d - ON 條件就是「怎麼配對」
- 一次可以 JOIN 多張表:
FROM a JOIN b ON ... JOIN c ON ...
Day 5:新增 / 更新 / 刪除
-- 新增
INSERT INTO employees (name, department, dept_id, salary, hire_date)
VALUES ('新人一號', 'IT', 1, 40000, '2025-01-15');
-- 一次新增多筆
INSERT INTO employees (name, department, dept_id, salary, hire_date) VALUES
('新人二號', 'Sales', 2, 38000, '2025-02-01'),
('新人三號', 'Production', 3, 35000, '2025-02-15');
-- 更新(千萬別漏 WHERE!)
UPDATE employees SET salary = 50000 WHERE id = 10;
-- 更新多欄位
UPDATE employees
SET salary = 55000, department = 'IT'
WHERE id = 5;
-- 刪除(千萬別漏 WHERE!)
DELETE FROM employees WHERE id = 10;
-
安全習慣(面試必講): 1. UPDATE/DELETE 之前一定先用 SELECT 確認影響範圍 2. 永遠加 WHERE,否則會改/刪「全部」資料 3. 在正式環境先在測試環境驗證 4. 重要操作前先備份
sql -- 先確認要改哪些 SELECT * FROM employees WHERE department = 'IT' AND salary < 40000; -- 確認無誤再改 UPDATE employees SET salary = 42000 WHERE department = 'IT' AND salary < 40000; -
子查詢(Subquery):
-- 查薪水高於平均的人
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- 查薪水最高的人
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
-- IN 子查詢:查 IT 或 Sales 部門的人
SELECT name FROM employees
WHERE dept_id IN (SELECT id FROM departments WHERE dept_name IN ('資訊部', '業務部'));
Day 6:30 題實戰演練
- 自己出或找題庫,涵蓋篩選、排序、分組、JOIN、子查詢
- 建議題目清單:
| # | 題目 | 考點 |
|---|---|---|
| 1 | 查所有 IT 部門員工 | WHERE |
| 2 | 查薪水前 3 高 | ORDER BY + LIMIT |
| 3 | 查 2024 年後到職的人 | WHERE + 日期比較 |
| 4 | 查姓「王」的人 | LIKE |
| 5 | 查薪水在 40000~50000 之間 | BETWEEN |
| 6 | 統計各部門人數 | GROUP BY + COUNT |
| 7 | 各部門平均薪資 | GROUP BY + AVG |
| 8 | 人數超過 2 的部門 | HAVING |
| 9 | 薪水最高的人 | MAX 或 ORDER+LIMIT |
| 10 | 薪水高於平均的人 | 子查詢 |
| 11 | IT 部門薪水前 5 高 | WHERE + ORDER + LIMIT |
| 12 | 各部門最高薪 | GROUP BY + MAX |
| 13 | 列出員工與部門名稱 | JOIN |
| 14 | 找沒部門的員工 | LEFT JOIN + IS NULL |
| 15 | 新增一筆員工 | INSERT |
| 16 | 調整某人薪水 | UPDATE + WHERE |
| 17 | 刪除已離職員工 | DELETE + WHERE |
| 18 | 各部門薪資總額 | GROUP BY + SUM |
| 19 | 到職最早的 3 人 | ORDER BY + LIMIT |
| 20 | 統計每年到職人數 | 日期函數 + GROUP BY |
| 21 | 薪水排名(不用 RANK) | 子查詢 |
| 22 | 同時查多表 | 多重 JOIN |
| 23 | 條件更新 | UPDATE + 條件 |
| 24 | 查重複資料 | GROUP BY + HAVING |
| 25 | 部門人數佔比 | 子查詢 + 計算 |
| 26 | 查 NULL 值 | IS NULL |
| 27 | CASE WHEN 分類 | 條件表達式 |
| 28 | 組合條件查詢 | AND/OR |
| 29 | 別名與格式化 | AS |
| 30 | 多條件排序 | ORDER BY 多欄位 |
- 目標:看到題目能直接寫出 SQL
Day 7:複習 + 手寫測驗
- 不看資料,手寫 5 題: 1. IT 部門薪水前 5 高 2. 各部門平均薪資(只列人數 > 2 的部門) 3. 2024 年後到職的員工與其部門名稱(JOIN) 4. 薪水高於全公司平均的員工 5. 新增一筆員工並更新其薪水
- 複習執行順序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
- 用自己的話解釋為什麼 WHERE 不能用聚合函數(因為 WHERE 在 GROUP BY 之前執行)
重點觀念速記
執行順序(必背)
FROM → 決定從哪張表取資料
WHERE → 篩選列(在分組前)
GROUP BY → 分組
HAVING → 篩選組(在分組後)
SELECT → 決定輸出哪些欄位
ORDER BY → 排序
LIMIT → 限制筆數
核心觀念
- WHERE 篩「列」、HAVING 篩「分組結果」
- WHERE 不能用聚合函數(因為還沒分組);HAVING 可以
- UPDATE/DELETE 一定加 WHERE(面試送分題)
- 改/刪前先用 SELECT 確認範圍
- 取前 N 名:MySQL/SQLite
LIMIT、SQL ServerTOP、OracleFETCH FIRST - INNER JOIN:兩邊都有才出現;LEFT JOIN:左表全保留
- NULL 要用 IS NULL 判斷,不能用 =
面試常考手寫
SELECT ... WHERE ... ORDER BY ... LIMIT(基本篩選排序)GROUP BY ... HAVING(分組統計)JOIN ... ON(多表關聯)子查詢(WHERE 中套 SELECT)
本週實作任務(產出)
任務一:建好測試資料庫
目標:建立兩張有關聯的表,塞入至少 10 筆測試資料。
步驟:
1. 選擇工具:SQLite(離線)或 DB Fiddle(線上)
2. 建立 departments 表(id, dept_name)
3. 建立 employees 表(id, name, department, dept_id, salary, hire_date)
4. 設定 FOREIGN KEY 關聯
5. INSERT 至少 10 筆員工、4 個部門的測試資料
6. 確認 SELECT * 能正確查詢
任務二:30 題查詢練習紀錄
目標:題目 + 你的 SQL + 結果。
格式建議:
## 題目 1:查出 IT 部門所有員工
SELECT name, salary FROM employees WHERE department = 'IT';
結果:4 筆(王小明、李小華、陳美麗、周大鵬)
## 題目 2:...
本週重要名詞對照表(中英對照)
| 中文 | 英文 | 說明 |
|---|---|---|
| 結構化查詢語言 | SQL (Structured Query Language) | 操作關聯式資料庫的語言 |
| 查詢 | SELECT | 讀取資料 |
| 篩選 | WHERE | 條件過濾 |
| 排序 | ORDER BY | 結果排序 |
| 分組 | GROUP BY | 依欄位分組統計 |
| 聚合函數 | Aggregate Functions | COUNT/SUM/AVG/MAX/MIN |
| 關聯 | JOIN | 連接多張表 |
| 內部關聯 | INNER JOIN | 兩表都有才保留 |
| 左外關聯 | LEFT JOIN | 左表全保留 |
| 子查詢 | Subquery | 查詢中的查詢 |
| 主鍵 | Primary Key | 唯一識別每筆資料 |
| 外鍵 | Foreign Key | 參照其他表的關聯欄位 |
| 空值 | NULL | 表示「沒有值」 |
| 別名 | Alias (AS) | 給欄位/表取暱稱 |
| 新增 | INSERT | 插入新資料 |
| 更新 | UPDATE | 修改既有資料 |
| 刪除 | DELETE | 移除資料 |
| 萬用字元 | Wildcard (%, _) | LIKE 模糊比對用 |
本週延伸閱讀資源
- SQLite Online:https://sqliteonline.com — 免安裝線上練習
- DB Fiddle:https://www.db-fiddle.com — 支援多種資料庫語法
- W3Schools SQL Tutorial:https://www.w3schools.com/sql — 基礎教學與線上練習
- LeetCode SQL 題庫:https://leetcode.com/problemset/database — 進階練習
- SQLZoo:https://sqlzoo.net — 互動式 SQL 教學
- Mode Analytics SQL Tutorial:較實務導向的 SQL 教學
- YouTube: SQL 教學(中文):搜尋「SQL 入門教學」
自我檢核
- [ ] 我能不看資料手寫 SELECT + WHERE + ORDER BY 查詢
- [ ] 我能用 GROUP BY 做分組統計並搭配 HAVING
- [ ] 我能寫 JOIN 關聯兩張表
- [ ] 我能解釋 INNER JOIN 與 LEFT JOIN 的差異
- [ ] 我知道 UPDATE/DELETE 一定要加 WHERE(並能說明原因)
- [ ] 我能說出 SQL 執行順序(FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY)
- [ ] 我能解釋 WHERE 和 HAVING 的差別
- [ ] 我能使用子查詢
- [ ] 我能處理 NULL 值(IS NULL)
- [ ] 我完成了 30 題 SQL 練習
- [ ] 我能在面試中 2 分鐘內手寫「IT 部門薪水前 5 高」的 SQL
⬅️ 上一週:第 5 週 | ➡️ 下一週:第 7 週 — Python/VBA 自動化 + 知識管理