本日主題:用 30 題把這週所學整合練熟 + 面試常見 SQL 題 預計時間:2.5 小時(動手日) 對應主教材:第 6.1 節


一、今日學習目標

  • [ ] 看到題目能直接寫出 SQL
  • [ ] 整合 WHERE / 排序 / 聚合 / 分組 / JOIN / 子查詢
  • [ ] 練習面試常見 SQL 題型

用第 1 天建立的 employeesdepartments 表來練。建議先自己寫,再看解答。


二、30 題題庫(附完整解答)

基礎查詢(1~8)

第 1 題:查出所有員工的姓名與薪水。

SELECT name, salary FROM employees;
name salary
王小明 52000
李大華 48000
陳美麗 45000
林志強 60000
張雅婷 55000
黃建宏 47000

第 2 題:查出 IT 部門的所有員工。

SELECT * FROM employees WHERE department = 'IT';

注意:字串要加單引號,且大小寫要與資料一致。


第 3 題:查薪水大於 50000 的員工。

SELECT name, salary FROM employees WHERE salary > 50000;

結果:王小明(52000)、林志強(60000)、張雅婷(55000)。


第 4 題:查薪水介於 45000~55000 的員工。

SELECT name, salary FROM employees
WHERE salary BETWEEN 45000 AND 55000;

BETWEEN 包含兩端(45000 和 55000 都包含)。 也可以寫成:WHERE salary >= 45000 AND salary <= 55000


第 5 題:查姓「王」的員工。

SELECT * FROM employees WHERE name LIKE '王%';

% 代表任意長度字元。'王%' 表示以「王」開頭。


第 6 題:查 IT 或維修部門的員工。

-- 方法 1:用 IN
SELECT * FROM employees WHERE department IN ('IT','維修');

-- 方法 2:用 OR
SELECT * FROM employees
WHERE department = 'IT' OR department = '維修';

IN 寫法更簡潔,多個值時推薦用 IN。


第 7 題:查所有員工,依薪水由高到低排序。

SELECT * FROM employees ORDER BY salary DESC;

DESC = 降冪(大到小),ASC = 升冪(小到大,預設)。


第 8 題:查薪水最高的前 3 名。

SELECT name, salary FROM employees
ORDER BY salary DESC
LIMIT 3;

結果:林志強(60000)、張雅婷(55000)、王小明(52000)。

SQL Server 語法:SELECT TOP 3 name, salary FROM employees ORDER BY salary DESC


聚合與分組(9~18)

第 9 題:算出全公司員工人數。

SELECT COUNT(*) AS 員工人數 FROM employees;

結果:6。


第 10 題:算出全公司平均薪水。

SELECT AVG(salary) AS 平均薪水 FROM employees;

結果:51166(取整數)。


第 11 題:算出最高薪與最低薪。

SELECT MAX(salary) AS 最高薪, MIN(salary) AS 最低薪 FROM employees;

結果:最高 60000、最低 45000。


第 12 題:算出薪水總和。

SELECT SUM(salary) AS 薪水總和 FROM employees;

結果:307000。


第 13 題:每個部門各有幾人。

SELECT department, COUNT(*) AS 人數
FROM employees
GROUP BY department;
department 人數
IT 3
會計 1
維修 2

第 14 題:每個部門的平均薪水。

SELECT department, AVG(salary) AS 平均薪水
FROM employees
GROUP BY department;
department 平均薪水
IT 51666
會計 45000
維修 53500

第 15 題:每個部門的最高薪。

SELECT department, MAX(salary) AS 最高薪
FROM employees
GROUP BY department;
department 最高薪
IT 55000
會計 45000
維修 60000

第 16 題:找出平均薪水大於 48000 的部門。

SELECT department, AVG(salary) AS 平均薪水
FROM employees
GROUP BY department
HAVING AVG(salary) > 48000;

結果:IT(51666)、維修(53500)。

關鍵:對聚合結果篩選要用 HAVING,不能用 WHERE。


第 17 題:找出人數超過 1 人的部門。

SELECT department, COUNT(*) AS 人數
FROM employees
GROUP BY department
HAVING COUNT(*) > 1;

結果:IT(3)、維修(2)。


第 18 題:2024 年(含)以後到職的員工人數。

SELECT COUNT(*) AS 人數
FROM employees
WHERE hire_date >= '2024-01-01';

結果:3(王小明 2024-03-01、張雅婷 2025-02-01、黃建宏 2024-11-11)。

日期比較用字串格式 'YYYY-MM-DD',SQLite 中以文字排序即可正確比較。


JOIN(19~24)

第 19 題:查每位員工姓名 + 部門名稱(用 dept_id 關聯)。

SELECT e.name, d.dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.id;
name dept_name
王小明 IT
李大華 IT
陳美麗 會計
林志強 維修
張雅婷 IT
黃建宏 維修

第 20 題:用 LEFT JOIN 列出所有部門,即使沒人也要顯示。

SELECT d.dept_name, e.name
FROM departments d
LEFT JOIN employees e ON e.dept_id = d.id;

如果某部門沒有員工,e.name 會顯示 NULL。 注意:departments 要放在左邊(FROM departments)。


第 21 題:每個部門名稱 + 人數。

SELECT d.dept_name, COUNT(e.id) AS 人數
FROM departments d
LEFT JOIN employees e ON e.dept_id = d.id
GROUP BY d.dept_name;

用 LEFT JOIN 確保沒人的部門也會顯示(人數為 0)。 用 COUNT(e.id) 而非 COUNT(*),因為 NULL 不計入。


第 22 題:每個部門名稱 + 平均薪水。

SELECT d.dept_name, AVG(e.salary) AS 平均薪水
FROM departments d
JOIN employees e ON e.dept_id = d.id
GROUP BY d.dept_name;

第 23 題:查 IT 部門(用部門表關聯)所有人的姓名。

SELECT e.name
FROM employees e
JOIN departments d ON e.dept_id = d.id
WHERE d.dept_name = 'IT';

透過 JOIN 用 departments 表的名稱來篩選,而非直接用 employees.department。


第 24 題:找出沒有任何員工的部門。

SELECT d.dept_name
FROM departments d
LEFT JOIN employees e ON e.dept_id = d.id
WHERE e.id IS NULL;

解題思路: 1. LEFT JOIN 保留所有部門 2. 沒有員工的部門,e.id 會是 NULL 3. 用 WHERE e.id IS NULL 篩出來

以目前的測試資料,三個部門都有員工,結果為空。可以先新增一個無人部門測試: INSERT INTO departments VALUES (4,'人資');


異動(25~30)

第 25 題:新增一名員工。

INSERT INTO employees (id, name, department, dept_id, salary, hire_date)
VALUES (7, '吳俊傑', 'IT', 1, 50000, '2025-05-01');

建議指定欄位名稱,不要用 INSERT INTO employees VALUES (...)


第 26 題:把某員工薪水調為 60000。

-- Step 1: 先確認目標
SELECT * FROM employees WHERE id = 7;

-- Step 2: 更新
UPDATE employees SET salary = 60000 WHERE id = 7;

-- Step 3: 驗證
SELECT * FROM employees WHERE id = 7;

三步驟:確認 → 更新 → 驗證。


第 27 題:把 IT 部門所有人加薪 2000。

-- 先看目前 IT 部門薪水
SELECT name, salary FROM employees WHERE department = 'IT';

-- 加薪
UPDATE employees SET salary = salary + 2000
WHERE department = 'IT';

-- 驗證
SELECT name, salary FROM employees WHERE department = 'IT';

salary = salary + 2000 做相對調整,而非設定絕對值。


第 28 題:刪除某一名員工(先 SELECT 確認)。

-- Step 1: 確認要刪的對象
SELECT * FROM employees WHERE id = 7;

-- Step 2: 確認只有 1 筆後刪除
DELETE FROM employees WHERE id = 7;

-- Step 3: 驗證已刪除
SELECT * FROM employees WHERE id = 7;  -- 應無結果

永遠先 SELECT 確認,再 DELETE。


第 29 題:把某員工的部門改成「維修」。

-- 要同時改 department 和 dept_id,保持資料一致
UPDATE employees
SET department = '維修', dept_id = 3
WHERE id = 2;

-- 驗證
SELECT * FROM employees WHERE id = 2;

注意:如果表有 department 文字欄位和 dept_id 數字欄位,兩個都要改。


第 30 題:統計調整後每個部門的平均薪水(驗證第 27 題的結果)。

SELECT department, COUNT(*) AS 人數, AVG(salary) AS 平均薪水
FROM employees
GROUP BY department;

驗證 IT 部門的平均薪水是否比原本多了約 2000。


三、面試常見 SQL 加分題(額外 10 題)

第 31 題:查出每個部門薪水最高的員工。

-- 方法:子查詢
SELECT e.name, e.department, e.salary
FROM employees e
WHERE e.salary = (
  SELECT MAX(salary) FROM employees
  WHERE department = e.department
);

這是「相關子查詢」(Correlated Subquery),內層查詢引用外層的 e.department。


第 32 題:查出薪水排名第 2 高的員工。

-- 方法 1:用 LIMIT + OFFSET
SELECT name, salary FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

-- 方法 2:子查詢排除最高薪
SELECT name, salary FROM employees
WHERE salary = (
  SELECT MAX(salary) FROM employees
  WHERE salary < (SELECT MAX(salary) FROM employees)
);

第 33 題:用 CASE WHEN 將員工分為高薪/中薪/一般,並統計各級人數。

SELECT
  CASE
    WHEN salary >= 55000 THEN '高薪'
    WHEN salary >= 48000 THEN '中薪'
    ELSE '一般'
  END AS 薪資等級,
  COUNT(*) AS 人數
FROM employees
GROUP BY
  CASE
    WHEN salary >= 55000 THEN '高薪'
    WHEN salary >= 48000 THEN '中薪'
    ELSE '一般'
  END;

第 34 題:查出到職日期最早的員工。

SELECT name, hire_date FROM employees
WHERE hire_date = (SELECT MIN(hire_date) FROM employees);

結果:林志強(2021-09-20)。


第 35 題:查出每個部門到職最久的員工。

SELECT e.name, e.department, e.hire_date
FROM employees e
WHERE e.hire_date = (
  SELECT MIN(hire_date) FROM employees
  WHERE department = e.department
);

第 36 題:建立一個 VIEW 顯示員工詳細資訊。

CREATE VIEW v_employee_detail AS
SELECT e.id, e.name, e.salary, e.hire_date,
       d.dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.id;

-- 使用 VIEW
SELECT * FROM v_employee_detail WHERE dept_name = 'IT';

第 37 題:查出薪水高於其部門平均的員工。

SELECT e.name, e.department, e.salary
FROM employees e
WHERE e.salary > (
  SELECT AVG(salary) FROM employees
  WHERE department = e.department
);

面試熱門題!使用「相關子查詢」比較個人薪水與其部門平均。


第 38 題:查出所有部門的薪水統計(人數、平均、最高、最低、總和)。

SELECT d.dept_name,
       COUNT(e.id) AS 人數,
       AVG(e.salary) AS 平均,
       MAX(e.salary) AS 最高,
       MIN(e.salary) AS 最低,
       SUM(e.salary) AS 總和
FROM departments d
LEFT JOIN employees e ON e.dept_id = d.id
GROUP BY d.dept_name;

第 39 題:查出 2023 年到 2024 年之間到職的員工,並依部門分組統計人數。

SELECT department, COUNT(*) AS 人數
FROM employees
WHERE hire_date BETWEEN '2023-01-01' AND '2024-12-31'
GROUP BY department;

第 40 題:為 employees 表的 department 欄位建立索引,並解釋為什麼。

CREATE INDEX idx_emp_department ON employees(department);

解釋:department 經常用在 WHERE 篩選和 GROUP BY 分組中,建立索引可以加速這些查詢。尤其在資料量大時(如上萬筆)效果顯著。


四、常見誤解

誤解 正確觀念
「30 題做完就夠了」 要能「不看答案寫出來」才算真的會,多練幾次
「面試只考 SELECT」 UPDATE/DELETE 和安全習慣也常被問
「子查詢太難不會考」 基本的子查詢(如找最高薪、高於平均)是常見面試題
「寫出來就好」 面試時要能「邊寫邊講」解題思路,展現邏輯能力

五、面試加分小知識

  • 面試手寫 SQL 技巧:先寫 FROM(確定資料來源),再寫 WHERE(篩選條件),最後寫 SELECT(要顯示什麼)。
  • NULL 陷阱:COUNT(*) 包含 NULL,COUNT(欄位) 排除 NULL,面試常考。
  • 執行順序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY,理解這個順序就不會搞混。
  • 相關子查詢 vs 非相關子查詢:非相關子查詢只執行一次,相關子查詢每列都執行一次(效能差但有時必要)。

六、今日實作任務(產出)

  • [ ] 完成 30 題(基礎),記錄你的 SQL 與結果
  • [ ] 挑戰面試加分題(31~40)
  • [ ] 標記寫不出來的題目,明天複習加強

七、延伸閱讀


八、今日檢核

  • [ ] 我完成了 30 題基礎題
  • [ ] 我能獨立寫出分組與 JOIN 的查詢
  • [ ] 我練習了面試加分題
  • [ ] 我知道自己還要加強哪幾題

⬅️ 上一天:Day 5 | 🏠 本週總覽 | ➡️ 下一天:Day 7 — 複習與手寫測驗