本文 AI 產出,尚未審核

MySQL 課程 – 條件查詢

主題:WHERE 條件運算子


簡介

在資料庫開發與維運過程中,資料的篩選是最常見也是最重要的工作之一。
WHERE 子句負責告訴 MySQL「只取出符合什麼條件的資料」,若沒有正確使用,可能會導致 資料遺漏、錯誤或效能低落

本單元將從最常見的比較運算子、邏輯運算子、集合運算子、字串模式比對與 NULL 判斷,逐一說明其語法與實務應用,並提供多個可直接套用的範例,幫助讀者在日常開發中快速寫出正確且效能良好的查詢。


核心概念

1. 基本比較運算子

運算子 說明 範例
= 等於 price = 100
<>!= 不等於 status <> 'active'
> 大於 age > 30
>= 大於或等於 score >= 80
< 小於 quantity < 10
<= 小於或等於 created_at <= '2024-12-31'
-- 範例 1:找出價格正好等於 100 元的商品
SELECT *
FROM products
WHERE price = 100;

/* 範例 2:找出年齡大於 30 歲且狀態為 'active' 的使用者 */
SELECT user_id, name, age
FROM users
WHERE age > 30 AND status = 'active';

/* 範例 3:找出庫存少於 10 件或已下架的商品 */
SELECT product_id, name, stock, discontinued
FROM inventory
WHERE stock < 10 OR discontinued = 1;

小技巧:若欄位上有索引,盡量使用 =><>=<= 等「範圍」比較,讓 MySQL 能利用索引加速搜尋。


2. 邏輯運算子

運算子 說明 範例
AND 同時滿足兩個條件 price > 50 AND stock > 0
OR 任一條件成立即符合 category = 'Books' OR category = 'Music'
NOT 取反,常與 INBETWEENLIKE 搭配 NOT (status = 'deleted')
-- 範例 4:同時符合「價格大於 50」且「庫存大於 0」的商品
SELECT product_id, name, price, stock
FROM products
WHERE price > 50 AND stock > 0;

/* 範例 5:找出屬於「書籍」或「音樂」類別,且未被刪除的項目 */
SELECT *
FROM items
WHERE (category = 'Books' OR category = 'Music')
  AND NOT deleted;

/* 範例 6:使用 NOT 搭配 BETWEEN,排除特定日期範圍 */
SELECT order_id, order_date, total
FROM orders
WHERE NOT order_date BETWEEN '2024-01-01' AND '2024-01-31';

注意AND 的優先順序高於 OR,必要時使用 括號 明確分組,避免邏輯錯誤。


3. 集合運算子

運算子 說明 範例
IN 欄位值在給定集合內 country IN ('TW', 'JP', 'KR')
NOT IN 欄位值不在集合內 status NOT IN ('inactive', 'banned')
BETWEEN … AND … 範圍(含兩端) price BETWEEN 100 AND 200
NOT BETWEEN 範圍之外 age NOT BETWEEN 18 AND 65
-- 範例 7:找出國家屬於台灣、日本或韓國的使用者
SELECT user_id, name, country
FROM users
WHERE country IN ('TW', 'JP', 'KR');

/* 範例 8:排除已停用或被封鎖的帳號 */
SELECT *
FROM accounts
WHERE status NOT IN ('inactive', 'banned');

/* 範例 9:搜尋價格介於 100~200 元的商品(含邊界) */
SELECT product_id, name, price
FROM products
WHERE price BETWEEN 100 AND 200;

最佳實踐IN 列表若超過 10~15 個元素,建議改用臨時表或子查詢,避免產生過多的 OR 條件影響效能。


4. 字串模式比對

運算子 說明 範例
LIKE 使用 %(任意字元)與 _(單一字元)做通配 name LIKE 'A%'
NOT LIKE 取反 email NOT LIKE '%@example.com'
REGEXP / RLIKE 正規表達式比對,支援更複雜的模式 phone REGEXP '^09[0-9]{8}$'
-- 範例 10:找出姓名以「王」開頭的員工
SELECT employee_id, name
FROM employees
WHERE name LIKE '王%';

/* 範例 11:排除所有使用公司域名的 Email */
SELECT user_id, email
FROM users
WHERE email NOT LIKE '%@mycompany.com';

/* 範例 12:使用正規表達式驗證台灣手機號碼格式 */
SELECT customer_id, phone
FROM customers
WHERE phone REGEXP '^09[0-9]{8}$';

提醒LIKE 在字串開頭使用通配符 %(如 '%abc')會導致全表掃描,效能最差。若必須前置通配,請考慮 全文索引(FULLTEXT) 或外部搜尋引擎。


5. NULL 判斷

運算子 說明 範例
IS NULL 欄位值為 NULL deleted_at IS NULL
IS NOT NULL 欄位值非 NULL updated_at IS NOT NULL
-- 範例 13:找出尚未被刪除的記錄
SELECT *
FROM posts
WHERE deleted_at IS NULL;

/* 範例 14:列出所有已更新過的使用者 */
SELECT user_id, last_login
FROM users
WHERE last_login IS NOT NULL;

關鍵概念:在 SQL 中,NULL 不是「空字串」或「0」,因此必須使用 IS NULL / IS NOT NULL 來比較,否則會得到 未知(UNKNOWN) 的結果。


常見陷阱與最佳實踐

陷阱 說明 解決方式
使用 = 比較 NULL col = NULL 永遠回傳 NULL(即不符合) 改用 col IS NULL
忘記加括號導致邏輯錯誤 A OR B AND C 會先算 B AND C 明確使用 (A OR B) AND C
LIKE '%xxx' 產生全表掃描 前置 % 使索引失效 改用全文索引或正規表達式
IN 列表過長 MySQL 會把 IN 轉成大量 OR,效能下降 使用臨時表或 JOIN
忽略資料類型差異 int 欄位與字串比較可能產生隱式轉換 確保比較值型別一致,或使用 CAST
使用 != 而非 <> 雖然兩者皆可,但標準 SQL 推薦 <> 建議統一使用 <>,提升可讀性

最佳實踐

  1. 盡量使用索引欄位作為 WHERE 條件,避免在非索引欄位上做大量運算。
  2. 把條件拆成易讀的子句,例如使用 CTE(Common Table Expression)或子查詢,提高維護性。
  3. 在大型資料表上加入適當的覆寫索引(covering index),讓 MySQL 只走索引即可返回結果。
  4. 使用參數化查詢(prepared statements)防止 SQL Injection,同時讓執行計畫可重用。

實際應用場景

場景 需求 WHERE 範例
電商商品搜尋 只顯示有庫存且價格在使用者指定範圍內的商品 WHERE stock > 0 AND price BETWEEN 500 AND 2000
會員行為分析 找出過去 30 天內登入且未購買的使用者 WHERE last_login >= CURDATE() - INTERVAL 30 DAY AND NOT EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)
HR 員工篩選 取得部門為「研發」且年資大於 5 年的員工 WHERE department = 'R&D' AND hire_date <= CURDATE() - INTERVAL 5 YEAR
客服工單統計 統計本月未解決的工單數量 WHERE status <> 'resolved' AND created_at BETWEEN DATE_FORMAT(CURDATE(),'%Y-%m-01') AND LAST_DAY(CURDATE())
IoT 裝置監控 找出最近 5 分鐘內未回傳心跳的裝置 WHERE last_heartbeat < NOW() - INTERVAL 5 MINUTE

總結

WHERE 子句是 MySQL 條件查詢 的核心,正確掌握 比較、邏輯、集合、字串與 NULL 判斷 等運算子,能讓你快速定位所需資料,同時保持查詢效能。

  • 了解需求,再選擇最適合的運算子與寫法。
  • 注意 運算子優先順序索引使用NULL 處理,可避免常見的陷阱。
  • 透過 最佳實踐(如使用參數化查詢、合理建索引、適當分組條件),可讓程式碼更安全、易維護且效能佳。

掌握了這些概念,你就能在日常開發、資料分析與系統優化中,寫出 既正確又高效 的 MySQL 查詢。祝你在 MySQL 的世界裡玩得開心、查得順利!