SELECT
[ALL | DISTINCT | DISTINCTROW]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT | SQL_BIG_RESULT]
[SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE]
[SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position} [ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
]
[INTO OUTFILE 'file_name' [CHARACTER SET charset_name] export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name] ...]
[FOR UPDATE | LOCK IN SHARE MODE];
| 修飾符 | 作用 | 適用場景 |
|---|---|---|
DISTINCT / DISTINCTROW | 結果去重 (NULL 視為相等) | 統計唯一值、去重報表 |
ALL | 保留所有行 (默認) | 顯式聲明意圖 |
HIGH_PRIORITY | 提升優先級,插隊執行 | 實時儀表板、緊急查詢 |
STRAIGHT_JOIN | 強制按 FROM 順序連接 | 優化器選錯連接順序時 |
SQL_SMALL_RESULT | 提示結果集小,用臨時表 | GROUP BY/DISTINCT 且確定小結果 |
SQL_BIG_RESULT | 提示結果集大,用排序 | 大數據集 GROUP BY/DISTINCT |
SQL_BUFFER_RESULT | 強制結果進臨時表,釋放鎖 | 長時間傳輸結果、減少鎖持有 |
SQL_CACHE / SQL_NO_CACHE | 控制查詢緩存 (5.7 已棄用,8.0 移除) | 歷史版本調優 |
SQL_CALC_FOUND_ROWS | 配合 LIMIT 獲取總行數 | 分頁查詢總數 (配合 FOUND_ROWS()) |
-- 1. 所有列
SELECT * FROM t;
-- 2. 指定列 + 別名 (AS 可省略)
SELECT id AS user_id, CONCAT(first_name, ' ', last_name) AS full_name FROM users;
-- 3. 表達式與函數
SELECT price * quantity AS total, ROUND(price * 1.1, 2) AS price_with_tax FROM orders;
-- 4. 聚合函數
SELECT COUNT(*), AVG(salary), MAX(hire_date) FROM employees;
-- 5. 窗口函數 (8.0+)
SELECT name, salary,
ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rn,
SUM(salary) OVER (PARTITION BY dept_id) AS dept_total
FROM employees;
-- 別名 (AS 可省略)
SELECT e.name, d.name AS dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.id;
-- 子查詢作派生表 (5.6+ 物化優化)
SELECT derived.dept_name, derived.avg_sal
FROM (SELECT d.name AS dept_name, AVG(e.salary) AS avg_sal
FROM employees e JOIN departments d ON e.dept_id = d.id
GROUP BY d.id) derived
WHERE derived.avg_sal > 5000;
=, <>, !=, >, <, >=, <=, <=> (NULL 安全等於)。BETWEEN ... AND ... (含邊界)。IN (...), NOT IN (...) (慎用 NOT IN 含 NULL 陷阱)。LIKE 'prefix%' (走索引), LIKE '%suffix' (全掃)。IS NULL, IS NOT NULL。AND 優先於 OR,用括號明確優先級。-- 分組聚合
SELECT dept_id, COUNT(*) AS cnt, AVG(salary) AS avg_sal
FROM employees
GROUP BY dept_id
HAVING COUNT(*) > 5; -- 過濾聚合後的組
-- WITH ROLLUP (超級聚合行)
SELECT dept_id, COUNT(*) FROM employees GROUP BY dept_id WITH ROLLUP;
-- 最後一行 dept_id=NULL 為總計
注意:HAVING 可引用聚合函數/別名;WHERE 不可。
ASC (默認) / DESC。NULLS FIRST / LAST (8.0.2+)。filesort。-- 前 10 行
LIMIT 10
-- 跳過 20 行取 10 行 (第 3 頁)
LIMIT 20, 10
-- 標準 SQL 寫法 (8.0+)
LIMIT 10 OFFSET 20
深分頁性能陷阱:LIMIT 1000000, 10 需掃描 100 萬行再丟棄。
優化:WHERE id > (SELECT id FROM t ORDER BY id LIMIT 1000000, 1) ORDER BY id LIMIT 10 (需唯一索引)。
-- CSV 導出 (服務器端文件,需 FILE 權限)
SELECT * FROM orders
INTO OUTFILE '/tmp/orders.csv'
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '\\'
LINES TERMINATED BY '\n';
SELECT a, b FROM t WHERE c = 1 → INDEX idx_c_ab (c, a, b),Extra: Using index,零回表。
-- ❌ 字符列比數字
WHERE phone = 13800138000
-- ✅
WHERE phone = '13800138000'
-- ❌ 兩列各有索引但 OR 導致全掃
WHERE a = 1 OR b = 2
-- ✅
SELECT * FROM t WHERE a = 1
UNION
SELECT * FROM t WHERE b = 2;
-- ✅ 相關子查詢,外表驅動
SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.t1_id = t1.id);
SELECT * FROM (SELECT ... FROM t) derived → 物化臨時表 + 索引,避免重複展開。
| 錯誤 | 正確做法 |
|---|---|
SELECT * 生產代碼 | 顯式列名,減少網絡、利用覆蓋索引 |
WHERE col = NULL | WHERE col IS NULL |
NOT IN (subquery 含 NULL) | NOT EXISTS (subquery) |
LIKE '%keyword%' 期望走索引 | 全文索引 / Elasticsearch / 前綴匹配 |
ORDER BY RAND() 隨機取樣 | 應用層隨機 ID / WHERE id >= (SELECT FLOOR(RAND()*MAX(id)) FROM t) LIMIT 1 |
深分頁 LIMIT 1000000, 10 | 游標分頁 / 延遲關聯 / 覆蓋索引 |
| 子查詢未加 LIMIT 導致物化巨大 | 加 LIMIT / 改 JOIN / 物化臨時表 |
SELECT 是 SQL 最核心、變體最豐富的語句。掌握 語法骨架 → 子句語義 → 優化修飾符 → 索引配合 → 反模式規避 五層知識,才能寫出既正確又高效的查詢。建議:每條上線 SQL 必經 EXPLAIN 驗證,慢查詢日誌定期審計,覆蓋索引作為首選優化手段。