本日主題:不靠工具,手寫 SQL(模擬面試白板題) 預計時間:1.5 小時 對應主教材:第 6.1 節
一、今日學習目標
- [ ] 複習 SQL 執行順序
- [ ] 不看資料手寫 SQL
- [ ] 準備面試 SQL 口述/白板題
- [ ] 複習本週所有觀念(含子查詢、VIEW、INDEX)
二、本週重點總複習
2.1 SQL 執行順序(理解這個就不會亂)
┌────────────────────────────────────────────────────────┐
│ SQL 執行順序 │
├────────────────────────────────────────────────────────┤
│ │
│ 書寫順序:SELECT → FROM → WHERE → GROUP BY → HAVING │
│ → ORDER BY → LIMIT │
│ │
│ 執行順序:FROM → WHERE → GROUP BY → HAVING → SELECT │
│ → ORDER BY → LIMIT │
│ │
│ ┌─────┐ │
│ │FROM │ ① 決定資料來源(哪張表) │
│ └──┬──┘ │
│ ↓ │
│ ┌─────┐ │
│ │WHERE│ ② 篩選個別列 │
│ └──┬──┘ │
│ ↓ │
│ ┌────────┐ │
│ │GROUP BY│ ③ 分組 │
│ └──┬─────┘ │
│ ↓ │
│ ┌──────┐ │
│ │HAVING│ ④ 篩選分組結果 │
│ └──┬───┘ │
│ ↓ │
│ ┌──────┐ │
│ │SELECT│ ⑤ 選擇要顯示的欄位 │
│ └──┬───┘ │
│ ↓ │
│ ┌────────┐ │
│ │ORDER BY│ ⑥ 排序結果 │
│ └──┬─────┘ │
│ ↓ │
│ ┌─────┐ │
│ │LIMIT│ ⑦ 取前 N 筆 │
│ └─────┘ │
└────────────────────────────────────────────────────────┘
2.2 重點速記
┌──────────────────────────────────────────────────────┐
│ 本週 SQL 知識地圖 │
├──────────────────────────────────────────────────────┤
│ │
│ Day 1:SELECT, FROM, WHERE, ORDER BY, DISTINCT, AS │
│ Day 2:BETWEEN, IN, LIKE, AND/OR, LIMIT, CASE WHEN │
│ Day 3:COUNT/SUM/AVG/MAX/MIN, GROUP BY, HAVING, 子查詢│
│ Day 4:INNER JOIN, LEFT JOIN, VIEW │
│ Day 5:INSERT, UPDATE, DELETE, Transaction, INDEX │
│ Day 6:30 題整合練習 + 面試加分題 │
│ │
│ ★ 高頻考點: │
│ 1. WHERE vs HAVING │
│ 2. INNER JOIN vs LEFT JOIN │
│ 3. UPDATE/DELETE 要加 WHERE │
│ 4. 子查詢(找最高薪、高於平均) │
│ 5. GROUP BY + 聚合函數 │
│ 6. SQL 執行順序 │
└──────────────────────────────────────────────────────┘
2.3 語法速查表
| 功能 | 語法 | 範例 |
|---|---|---|
| 查詢 | SELECT ... FROM ... | SELECT name FROM employees |
| 篩選 | WHERE | WHERE salary > 50000 |
| 排序 | ORDER BY ... ASC/DESC | ORDER BY salary DESC |
| 取前 N | LIMIT N | LIMIT 3 |
| 去重複 | DISTINCT | SELECT DISTINCT department |
| 別名 | AS | salary AS 薪水 |
| 模糊查 | LIKE | WHERE name LIKE '王%' |
| 範圍 | BETWEEN ... AND ... | BETWEEN 45000 AND 55000 |
| 清單 | IN (...) | IN ('IT','維修') |
| 聚合 | COUNT/SUM/AVG/MAX/MIN | COUNT(*), AVG(salary) |
| 分組 | GROUP BY | GROUP BY department |
| 分組篩選 | HAVING | HAVING COUNT(*) > 1 |
| 關聯 | JOIN ... ON | JOIN departments d ON e.dept_id = d.id |
| 左關聯 | LEFT JOIN | LEFT JOIN ... ON ... |
| 條件值 | CASE WHEN ... THEN ... END | CASE WHEN salary>50000 THEN '高' END |
| 新增 | INSERT INTO | INSERT INTO employees VALUES (...) |
| 更新 | UPDATE ... SET ... WHERE | UPDATE employees SET salary=60000 WHERE id=1 |
| 刪除 | DELETE FROM ... WHERE | DELETE FROM employees WHERE id=1 |
| 建索引 | CREATE INDEX | CREATE INDEX idx ON employees(department) |
| 建檢視 | CREATE VIEW | CREATE VIEW v AS SELECT ... |
| 子查詢 | (SELECT ...) | WHERE salary > (SELECT AVG(salary) FROM ...) |
三、手寫測驗(不看工具,紙上寫)
基礎篇(Q1~Q5)
Q1. 查 IT 部門薪水前 5 高(姓名、薪水)。
Q2. 統計每個部門的人數與平均薪水。
Q3. 查 2024 年以後到職的員工。
Q4. 用 JOIN 顯示每位員工的姓名與部門名稱。
Q5. 把 id=3 的員工薪水改成 50000。
進階篇(Q6~Q10)
Q6. 查出薪水高於全公司平均的員工(用子查詢)。
Q7. 用 CASE WHEN 將員工依薪水分為高/中/低三級。
Q8. 查出每個部門薪水最高的員工姓名。
Q9. 找出沒有員工的部門(用 LEFT JOIN)。
Q10. 建立一個 VIEW 顯示員工姓名、薪水、部門名稱,然後查詢薪水大於 50000 的資料。
參考解答
-- Q1:IT 部門薪水前 5 高
SELECT name, salary FROM employees
WHERE department = 'IT'
ORDER BY salary DESC LIMIT 5;
-- Q2:每部門人數與平均薪水
SELECT department, COUNT(*) AS 人數, AVG(salary) AS 平均薪水
FROM employees GROUP BY department;
-- Q3:2024 年以後到職
SELECT name, hire_date FROM employees
WHERE hire_date >= '2024-01-01';
-- Q4:JOIN 顯示員工與部門名稱
SELECT e.name, d.dept_name
FROM employees e JOIN departments d ON e.dept_id = d.id;
-- Q5:更新薪水(含安全確認)
-- 先確認:SELECT * FROM employees WHERE id = 3;
UPDATE employees SET salary = 50000 WHERE id = 3;
-- Q6:薪水高於平均(子查詢)
SELECT name, salary FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- Q7:CASE WHEN 薪資分級
SELECT name, salary,
CASE
WHEN salary >= 55000 THEN '高薪'
WHEN salary >= 48000 THEN '中薪'
ELSE '一般'
END AS 薪資等級
FROM employees;
-- Q8:每部門薪水最高的員工
SELECT e.name, e.department, e.salary
FROM employees e
WHERE e.salary = (
SELECT MAX(salary) FROM employees
WHERE department = e.department
);
-- Q9:沒有員工的部門
SELECT d.dept_name
FROM departments d
LEFT JOIN employees e ON e.dept_id = d.id
WHERE e.id IS NULL;
-- Q10:建立 VIEW 並查詢
CREATE VIEW v_emp_info AS
SELECT e.name AS 姓名, e.salary AS 薪水, d.dept_name AS 部門
FROM employees e
JOIN departments d ON e.dept_id = d.id;
SELECT * FROM v_emp_info WHERE 薪水 > 50000;
四、面試口述演練
4.1 被問「查 IT 部門薪水前 5 高怎麼寫」
邊講邊寫: 「我會先 FROM employees,然後 WHERE department = 'IT' 篩選 IT 部門,再 ORDER BY salary DESC 依薪水由高到低排序,最後 LIMIT 5 取前 5 名。SELECT 的部分選 name 和 salary。」
加分:主動提到「不同資料庫取前 N 名語法不同,MySQL/SQLite 用 LIMIT,SQL Server 用 TOP,Oracle 用 FETCH FIRST」。
4.2 被問「WHERE 和 HAVING 差在哪」
「WHERE 是在分組前篩選個別資料列,不能用聚合函數;HAVING 是在 GROUP BY 分組後篩選分組結果,可以用聚合函數。」 「例如我要找人數超過 3 人的部門,不能用 WHERE COUNT()>3,要用 HAVING COUNT()>3。」
4.3 被問「INNER JOIN 和 LEFT JOIN 差在哪」
「INNER JOIN 只回傳兩邊都對得上的資料,LEFT JOIN 保留左表全部資料,右表沒對到的補 NULL。」 「例如我要列出所有部門包含沒有員工的,就要用 LEFT JOIN。」
4.4 被問「UPDATE 要注意什麼」
「最重要的是一定要加 WHERE 條件,不然會更新整張表。我的習慣是先用 SELECT + 同樣的 WHERE 確認影響範圍,確認只有要改的那幾筆後,再把 SELECT 改成 UPDATE。」 「在正式環境會先 BEGIN TRANSACTION,確認結果正確再 COMMIT,做錯了可以 ROLLBACK。」
4.5 被問「什麼是 INDEX」
「INDEX 像書的目錄,讓資料庫不用掃描整張表就能快速定位資料。通常在 WHERE、JOIN、ORDER BY 常用的欄位上建立。」 「但 INDEX 不是越多越好,因為每次 INSERT/UPDATE/DELETE 都要同步更新索引,會拖慢寫入效能。」
五、常見誤解總整理
| 誤解 | 正確觀念 |
|---|---|
| 「SQL 語法順序就是執行順序」 | 寫的順序是 SELECT→FROM→WHERE,但執行順序是 FROM→WHERE→SELECT |
| 「手寫 SQL 不重要」 | 面試白板題就是考手寫,要能不看工具寫出正確的 SQL |
| 「會 SELECT 就夠了」 | 還要會 UPDATE/DELETE(含安全習慣)、子查詢、JOIN、GROUP BY |
| 「背語法就好」 | 理解概念更重要,例如 WHERE vs HAVING 的差異 |
六、面試加分小知識
- Explain Plan:用 EXPLAIN 查看查詢執行計畫,了解資料庫如何處理你的 SQL。
- 正規化(Normalization):把資料拆到多張表避免重複,1NF/2NF/3NF 是三個層級。
- 反正規化(Denormalization):為了查詢效能,有時會故意保留一些重複資料。
- Stored Procedure(預存程序):把常用的 SQL 邏輯存在資料庫中,可重複呼叫。
- Trigger(觸發器):當資料被 INSERT/UPDATE/DELETE 時自動執行的 SQL。
- ORM(Object-Relational Mapping):用程式語言的物件操作資料庫,不直接寫 SQL(如 Django ORM、SQLAlchemy)。但面試通常要求你會「原生 SQL」。
七、自我評估檢查表
完成以下每項確認你的 SQL 能力:
| 能力 | 我能不看答案寫出來嗎? |
|---|---|
| SELECT + WHERE + ORDER BY | ☐ |
| BETWEEN / IN / LIKE | ☐ |
| AND / OR(含括號) | ☐ |
| LIMIT(取前 N) | ☐ |
| DISTINCT / AS | ☐ |
| COUNT / SUM / AVG / MAX / MIN | ☐ |
| GROUP BY + HAVING | ☐ |
| INNER JOIN | ☐ |
| LEFT JOIN | ☐ |
| 子查詢(WHERE 裡的 subquery) | ☐ |
| CASE WHEN | ☐ |
| INSERT / UPDATE / DELETE | ☐ |
| UPDATE/DELETE 前先 SELECT 確認 | ☐ |
| VIEW 建立與使用 | ☐ |
| INDEX 觀念 | ☐ |
| 說出 SQL 執行順序 | ☐ |
| 口述 WHERE vs HAVING 差異 | ☐ |
| 口述 INNER JOIN vs LEFT JOIN 差異 | ☐ |
目標:全部打勾才算準備好面試。
八、延伸閱讀
- SQL 面試準備指南 — Mode Analytics 的 SQL 教程
- LeetCode 資料庫題庫 — 持續練習的好地方
- SQL 執行順序圖解 — 知名部落格文章
九、本週結算檢核
- [ ] 手寫測驗 10 題全對(基礎 5 + 進階 5)
- [ ] 完成 30 題實戰(Day 6)
- [ ] 挑戰面試加分題(Day 6 的 31~40)
- [ ] 能說出 SQL 執行順序
- [ ] 能口述常見查詢的寫法
- [ ] 自我評估檢查表全部打勾
完成 → 第 6 週(SQL 重點)結束!下週進入自動化與知識管理。
⬅️ 上一天:Day 6 | 🏠 本週總覽 | ➡️ 下一週:第 7 週 Day 1