MySQL 課程 – 條件查詢:IN、BETWEEN、LIKE
簡介
在日常開發中,資料檢索往往是最頻繁的工作。即使是最簡單的 SELECT,也常需要根據多種條件過濾資料。IN、BETWEEN 與 LIKE 是 MySQL 中最常見的三種條件運算子,掌握它們的用法可以讓你在 資料庫查詢 時寫出更簡潔、可讀性更高的 SQL,並且在效能上獲得明顯提升。
本篇文章將從概念說明、實作範例、常見陷阱與最佳實踐,逐步帶領讀者了解這三種運算子,並提供 實務應用情境,幫助你在專案中快速上手、寫出可靠的條件查詢。
核心概念
1. IN – 多值比對
IN 用來判斷欄位的值是否 屬於 一組指定的集合。等價於多個 OR 條件的組合,但語法更簡潔且可讀性更好。
SELECT *
FROM employees
WHERE department_id IN (1, 3, 5);
- 上例會回傳部門代號為 1、3、5 的所有員工。
IN也可以搭配子查詢,動態產生比較集合:
SELECT *
FROM orders
WHERE customer_id IN (
SELECT id FROM customers WHERE country = 'TW'
);
小技巧:當集合裡的值較少時,使用
IN效能通常比多個OR更好;若集合非常大,考慮改用 JOIN 或 EXISTS。
2. BETWEEN – 範圍查詢
BETWEEN 用於 範圍 判斷,語法是 value BETWEEN low AND high,兩端皆包含在內。
SELECT *
FROM sales
WHERE sale_date BETWEEN '2024-01-01' AND '2024-01-31';
- 以上查詢會取得 2024 年 1 月整個月的銷售紀錄。
BETWEEN也支援數值型別:
SELECT product_id, price
FROM products
WHERE price BETWEEN 100 AND 500;
注意:
BETWEEN只適用於可比較的資料型別(數值、日期、字串)。若資料類型不一致,MySQL 會自動做隱式轉換,可能造成意外結果,建議在使用前先確保欄位與常數的型別相符。
3. LIKE – 模糊字串比對
LIKE 提供 通配符(Wildcard)比對功能,常用於搜尋部分文字。
| 通配符 | 說明 |
|---|---|
% |
代表任意長度(含 0)字元 |
_ |
代表單一字元 |
-- 找出姓名以「王」開頭的員工
SELECT *
FROM employees
WHERE name LIKE '王%';
-- 找出電話號碼第 3 位是「9」的客戶
SELECT *
FROM customers
WHERE phone LIKE '__9%';
最佳實踐:若想要搜尋不分大小寫,可使用
COLLATE或將欄位設為 ci(case‑insensitive)排序規則;若要提升效能,盡量避免在索引欄位的最左側使用%(例如%abc),因為這會導致索引失效。
程式碼範例彙總
以下示範結合三種運算子,完成一個較為完整的查詢需求:
/* 需求說明:
1. 只取出「台北」或「新竹」的門市 (IN)
2. 銷售日期在 2024 Q1 之間 (BETWEEN)
3. 商品名稱包含「手機」關鍵字 (LIKE)
*/
SELECT s.store_id, s.store_name, p.product_name, o.amount, o.sale_date
FROM sales AS o
JOIN stores AS s ON o.store_id = s.store_id
JOIN products AS p ON o.product_id = p.product_id
WHERE s.city IN ('台北', '新竹')
AND o.sale_date BETWEEN '2024-01-01' AND '2024-03-31'
AND p.product_name LIKE '%手機%';
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方式 / 最佳實踐 |
|---|---|---|
IN 內部空集合 |
WHERE col IN () 會產生語法錯誤或永遠回傳空集合。 |
在產生動態 SQL 時,先檢查集合是否為空;若空則改用 WHERE 1=0 或直接跳過查詢。 |
BETWEEN 與時間 |
若欄位是 DATETIME,BETWEEN '2024-01-01' AND '2024-01-31' 會漏掉 1 月 31 日的 23:59:59 時間。 |
使用 BETWEEN '2024-01-01' AND '2024-01-31 23:59:59',或改寫為 >= & <(左閉右開)方式。 |
LIKE 前置 % |
%abc 會使索引失效,導致全表掃描。 |
若可能,改用 全文索引(FULLTEXT)或 倒排索引;若必須使用 %,考慮先把資料切分成可搜尋的子字串。 |
| 大小寫敏感 | 預設依照欄位的排序規則(collation)決定是否區分大小寫。 | 明確指定 COLLATE utf8mb4_general_ci 或使用 LOWER()/UPPER() 包裝欄位與字串。 |
| 資料型別不一致 | BETWEEN 與 IN 若比較的值與欄位型別不同,MySQL 會自動轉型,可能產生意外結果。 |
在寫 SQL 前,先確認常數的型別與欄位相符(如日期加上單引號、數值不加引號)。 |
效能小技巧
- 使用索引:
IN、BETWEEN、LIKE(左側不含%)皆可受索引加速。 - 適度限制返回列數:配合
LIMIT及分頁(OFFSET)減少一次查詢的負載。 - 避免過度使用子查詢:若子查詢結果集很大,考慮改寫為 JOIN 或 CTE(MySQL 8.0+)。
實際應用場景
| 場景 | 需求 | 運算子選擇 | 範例 SQL |
|---|---|---|---|
| 客製化報表 | 產生本月各門市的銷售總額 | BETWEEN(日期範圍)+ IN(門市清單) |
SELECT store_id, SUM(amount) FROM sales WHERE store_id IN (101,102) AND sale_date BETWEEN CURDATE()-INTERVAL 30 DAY AND CURDATE() GROUP BY store_id; |
| 關鍵字搜尋 | 前端搜尋框允許使用 *、? 通配符 |
轉換為 LIKE(*→%、?→_) |
SELECT * FROM articles WHERE title LIKE REPLACE(REPLACE(:keyword,'*','%'),'?','_'); |
| 會員分層 | 依照消費金額分成「銀卡」(0 |
BETWEEN |
SELECT member_id, CASE WHEN total BETWEEN 0 AND 999 THEN '銀卡' WHEN total BETWEEN 1000 AND 4999 THEN '金卡' ELSE '白金卡' END AS tier FROM member_spending; |
| 多國語系資料過濾 | 只顯示特定國家/地區的使用者 | IN + LIKE(語系代碼) |
SELECT * FROM users WHERE country IN ('TW','HK','MO') AND locale LIKE 'zh_TW%'; |
總結
IN:適合「多值等於」的情境,語法簡潔且可搭配子查詢。BETWEEN:用於閉區間範圍查詢,特別適合日期與數值範圍。注意左閉右閉的特性,必要時改用>=/<。LIKE:提供字串的模糊搜尋,配合%、_通配符,可實作關鍵字、前綴、後綴搜尋。使用時要留意索引失效與大小寫問題。
在實務開發中,正確選擇運算子、配合索引與適當的寫法,不僅能提升程式碼可讀性,也能顯著降低查詢延遲。希望本篇文章能幫助你在 MySQL 條件查詢上更得心應手,寫出高效、易維護的 SQL。祝你在資料庫開發的道路上越走越遠!