本日主題:更靈活的 WHERE 條件與排序、取前 N 名 預計時間:1.5 小時 對應主教材:第 6.1 節


一、今日學習目標

  • [ ] 熟練各種 WHERE 條件運算子
  • [ ] 會多欄位排序與取前 N 名
  • [ ] 認識 CASE WHEN 條件表達式

二、教材內容

2.1 WHERE 常用運算子

WHERE salary > 50000              -- 大於
WHERE salary >= 50000             -- 大於等於
WHERE salary < 50000              -- 小於
WHERE salary <= 50000             -- 小於等於
WHERE department <> 'IT'          -- 不等於(也可用 !=)
WHERE salary BETWEEN 45000 AND 55000   -- 介於(含兩端)
WHERE department IN ('IT','維修')  -- 在清單內
WHERE name LIKE '王%'             -- 開頭是「王」(% 是萬用字元)
WHERE name LIKE '%華'             -- 結尾是「華」
WHERE hire_date IS NULL           -- 是空值
WHERE hire_date IS NOT NULL       -- 不是空值

2.2 多條件:AND / OR

-- AND:兩條件都要滿足
SELECT * FROM employees
WHERE department = 'IT' AND salary > 50000;

-- OR:任一條件滿足即可
SELECT * FROM employees
WHERE department = 'IT' OR department = '維修';

-- NOT:否定條件
SELECT * FROM employees
WHERE NOT department = 'IT';

混用 AND/OR 時用括號釐清優先順序:WHERE (a OR b) AND c

常見錯誤示範:

-- ❌ 錯誤:AND/OR 混用沒加括號,結果可能不如預期
SELECT * FROM employees
WHERE department = 'IT' OR department = '維修' AND salary > 50000;
-- 這等同於:WHERE department = 'IT' OR (department = '維修' AND salary > 50000)
-- 因為 AND 優先於 OR

-- ✓ 正確:加括號明確意圖
SELECT * FROM employees
WHERE (department = 'IT' OR department = '維修') AND salary > 50000;

2.3 排序與取前 N 名

-- 多欄位排序:先部門升冪,同部門再薪水降冪
SELECT * FROM employees
ORDER BY department ASC, salary DESC;

-- 取薪水前 3 名
SELECT name, salary FROM employees
ORDER BY salary DESC
LIMIT 3;            -- MySQL/SQLite/PostgreSQL
-- SQL Server: SELECT TOP 3 name, salary FROM employees ORDER BY salary DESC
-- Oracle:     SELECT name, salary FROM employees ORDER BY salary DESC FETCH FIRST 3 ROWS ONLY

2.4 LIKE 萬用字元

萬用字元 作用 範例 比對
% 任意長度字元(含 0 個) LIKE '王%' 王、王小明、王大華
_ 任意「單一」字元 LIKE '王_明' 王小明(中間剛好一個字)
-- 姓名包含「華」
SELECT * FROM employees WHERE name LIKE '%華%';

-- 姓名第二個字是「大」
SELECT * FROM employees WHERE name LIKE '_大%';

2.5 CASE WHEN 條件表達式

CASE WHEN 像是 SQL 裡的 if-else,可以根據條件產生不同的值:

-- 基本語法
SELECT name, salary,
  CASE
    WHEN salary >= 55000 THEN '高薪'
    WHEN salary >= 48000 THEN '中薪'
    ELSE '一般'
  END AS 薪資等級
FROM employees;

執行結果: | name | salary | 薪資等級 | |---|---|---| | 王小明 | 52000 | 中薪 | | 李大華 | 48000 | 中薪 | | 陳美麗 | 45000 | 一般 | | 林志強 | 60000 | 高薪 | | 張雅婷 | 55000 | 高薪 | | 黃建宏 | 47000 | 一般 |

-- 搭配 GROUP BY 使用:統計各薪資等級人數
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;

常見錯誤示範:

-- ❌ 錯誤:CASE WHEN 忘記 END
SELECT name,
  CASE WHEN salary > 50000 THEN '高' ELSE '低'
FROM employees;
-- 正確:CASE ... END

-- ❌ 錯誤:WHEN 條件順序不對
SELECT name,
  CASE
    WHEN salary >= 48000 THEN '中薪'  -- 這行先比對
    WHEN salary >= 55000 THEN '高薪'  -- 55000 也 >= 48000,永遠不會到這行
    ELSE '一般'
  END AS 等級
FROM employees;
-- 正確:從大到小排列 WHEN 條件

2.6 NULL 值的特殊處理

-- NULL 不能用 = 比較,要用 IS NULL / IS NOT NULL
-- ❌ 錯誤
SELECT * FROM employees WHERE hire_date = NULL;
-- ✓ 正確
SELECT * FROM employees WHERE hire_date IS NULL;

-- COALESCE:NULL 替換為預設值
SELECT name, COALESCE(department, '未指派') AS 部門
FROM employees;

三、常見誤解

誤解 正確觀念
「BETWEEN 不含邊界」 BETWEEN 包含左右兩端(BETWEEN 45000 AND 55000 包含 45000 和 55000)
「NULL = NULL 是 TRUE」 NULL = NULL 結果是 NULL(未知),不是 TRUE。要用 IS NULL
「LIKE '%' 效能跟 = 一樣」 LIKE 開頭用 % 會導致全表掃描,無法使用索引,效能差
「LIMIT 在所有資料庫都能用」 LIMIT 是 MySQL/SQLite/PostgreSQL 語法,SQL Server 用 TOP,Oracle 用 FETCH FIRST

四、面試加分小知識

  • Wildcard(萬用字元)%_ 的英文名稱。
  • Short-circuit evaluation:SQL 的 AND/OR 可能有短路評估,AND 左邊為 FALSE 時不評估右邊。
  • ILIKE:PostgreSQL 的大小寫不敏感 LIKE(MySQL 的 LIKE 預設就不分大小寫)。
  • ESCAPE:當 LIKE 要搜尋含 %_ 的實際字元時,用 ESCAPE 指定跳脫字元。

五、今日練習

Q1. 查薪水在 45000~55000 之間的員工。

Q2. 查 IT 或會計部門、且薪水大於 47000 的員工。

Q3. 查薪水最高的前 2 名(姓名、薪水)。

Q4. 用 CASE WHEN 將員工依薪水分為「高薪(>=55000)」「中薪(>=48000)」「一般」三級,顯示姓名與等級。

Q5. 查出所有姓「李」或姓「王」的員工。

參考解答
-- A1:薪水 45000~55000
SELECT * FROM employees WHERE salary BETWEEN 45000 AND 55000;

-- A2:(IT 或會計) 且薪水 > 47000
SELECT * FROM employees
WHERE department IN ('IT','會計') AND salary > 47000;
-- 或用括號明確表達:
-- WHERE (department = 'IT' OR department = '會計') AND salary > 47000;

-- A3:薪水前 2 名
SELECT name, salary FROM employees ORDER BY salary DESC LIMIT 2;

-- A4:CASE WHEN 薪資分級
SELECT name,
  CASE
    WHEN salary >= 55000 THEN '高薪'
    WHEN salary >= 48000 THEN '中薪'
    ELSE '一般'
  END AS 薪資等級
FROM employees;

-- A5:姓李或姓王
SELECT * FROM employees
WHERE name LIKE '李%' OR name LIKE '王%';

六、延伸閱讀


七、今日檢核

  • [ ] 我會用 BETWEEN/IN/LIKE 等運算子
  • [ ] 我會用 AND/OR 組合條件(含括號)
  • [ ] 我會多欄位排序與取前 N 名
  • [ ] 我會用 CASE WHEN 做條件判斷
  • [ ] 我知道 NULL 的特殊處理方式

⬅️ 上一天:Day 1 | 🏠 本週總覽 | ➡️ 下一天:Day 3 — 聚合與分組