SQL 查詢是後端開發的核心技能。本文整理 SELECT 實用技巧:語句格式、批次查詢、字串連接、定位搜尋、群組聚合、條件篩選、去重、分頁、多表連接,附帶常見陷阱與優化提示。
MySQL 允許 SQL 字串跨行,建議長查詢採用多行縮排:
$sql = "SELECT *
FROM article
WHERE id = 1";
便於維護與除錯,特別是動態組裝 SQL 時。
SELECT * FROM article WHERE id IN (1,3,5);
JOIN 衍生表。SELECT CONCAT(id, '-', content) AS res FROM article WHERE id = 1;
-- 輸出: 1-article content
常用於前端直接顯示的組合欄位(如「姓名-工號」)。
SELECT LOCATE('hello', 'hello baby'); -- 返回 1(找到位置)
SELECT LOCATE('xyz', 'hello baby'); -- 返回 0(不存在)
LOCATE(substr, str[, pos]) 可指定起始搜尋位置。WHERE LOCATE(keyword, column) > 0 實現簡易全文搜尋(小資料量)。-- 列出每個城市的客戶數
SELECT city, COUNT(*) AS cnt FROM customer GROUP BY city;
GROUP BY 將相同值的列分為一組,配合聚合函數(COUNT, SUM, AVG, MAX, MIN)產出統計。ONLY_FULL_GROUP_BY 模式下,SELECT 清單中的非聚合欄位必須出現在 GROUP BY 中。SELECT city, COUNT(*) AS cnt, MIN(birth_day) AS earliest
FROM customer
GROUP BY city
HAVING COUNT(*) > 10;
HAVING 在分組後篩選,可使用聚合函數;WHERE 在分組前篩選,不可用聚合函數。HAVING 中的運算式必須在 SELECT 或 GROUP BY 中出現過(或為聚合函數)。GROUP BY + HAVING 較慢,能用 WHERE 先過濾盡量用 WHERE。邏輯執行順序(非語法順序):
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
撰寫 SQL 時按語法順序:SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT。
SELECT DISTINCT city FROM customer ORDER BY id DESC;
SELECT 清單所有欄位組合去重。GROUP BY 或視窗函數(MySQL 8.0+ ROW_NUMBER())。-- 跳過前 100 筆,取後續所有(-1 表示無上限)
SELECT * FROM article LIMIT 100, -1;
-- 標準分頁:第 3 頁,每頁 20 筆
SELECT * FROM article LIMIT 40, 20; -- OFFSET 40 ROWS FETCH NEXT 20 ROWS ONLY (MySQL 8.0)
LIMIT offset, count 或 LIMIT count OFFSET offset。LIMIT 1000000, 20)效能差,建議改用游標分頁(WHERE id > last_id LIMIT 20)。SELECT u.user_name
FROM user u
JOIN member m ON u.id = m.id
WHERE m.reg_date >= '2006-12-28'
ORDER BY u.id DESC;
u, m)簡化欄位引用。u.user_name),否則報錯 Column 'user_name' in field list is ambiguous。JOIN ... ON 語法,避免舊式逗號連接產生笛卡兒積。| 情境 | 錯誤做法 | 正確做法 |
|---|---|---|
| GROUP BY 非聚合欄位 | SELECT id, city, COUNT(*) FROM t GROUP BY city | 加入 id 到 GROUP BY 或用聚合函數 MAX(id) |
| WHERE 用聚合函數 | SELECT city FROM t WHERE COUNT(*) > 10 | 改用 HAVING COUNT(*) > 10 |
| 分頁大偏移 | LIMIT 1000000, 20 | 游標分頁 WHERE id > 1000000 LIMIT 20 |
| 多表同名欄位 | SELECT user_name FROM u, m WHERE u.id=m.id | 加別名 SELECT u.user_name ... |
熟練這些技巧,能寫出更精準、高效、可維護的 SQL 查詢。