首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 資料檢索完全指南:SELECT 語法、連接類型、子查詢與實戰解決方案

     編輯:MySQL 資料庫相關知識

前言

SELECT 是 SQL 中最核心、變化最豐富、也是效能差異最大的指令。從簡單的單表查詢到複雜的多表連接、子查詢、視圖、CTE,掌握連接類型語意、WHERE/HAVING 過濾邏輯、GROUP BY 聚合規則、ORDER BY/LIMIT 分頁優化,是開發高效能應用的關鍵。本文系統整理 MySQL 支援的各類連接操作、欄位限定規則、別名應用、實戰解決方案模式,並以簡潔範例表格說明每種連接的資料集特徵。

一、SELECT 基礎語法架構

SELECT [DISTINCT] select_expr, ...
FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position} [ASC|DESC], ...]
[HAVING where_condition]
[ORDER BY {col_name | expr | position} [ASC|DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]

MySQL 特有:FROM 子句可省略(純表達式求值),LIMIT 支援 OFFSET 語法。

二、連接類型完整圖解

以兩張範例表示範:

t1:  id  val
      1   a
      2   b

t2:  id  val
      1   x
      3   y

1. 平凡連接 / 單表查詢

SELECT * FROM t1;

結果:t1 所有列。

2. 全連接 / 交叉連接 / 笛卡兒積

SELECT * FROM t1, t2;
-- 或
SELECT * FROM t1 CROSS JOIN t2;
-- 或
SELECT * FROM t1 INNER JOIN t2;  -- 無 ON 條件等同 CROSS JOIN

結果:4 列(2×2),所有組合。極度危險,大表會產生爆炸性列數,必須配合 WHERE 過濾。

3. 等值連接 / 內連接

SELECT * FROM t1, t2 WHERE t1.id = t2.id;
-- 标准语法
SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.id;
SELECT * FROM t1 JOIN t2 ON t1.id = t2.id;

結果:僅 id=1 符合,1 列。INNER JOIN、JOIN、CROSS JOIN 在有 ON 條件時語意相同。

4. 左外連接

SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.id;
-- 同義詞
SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.id = t2.id;
-- ODBC 語法
SELECT * FROM {OJ t1 LEFT OUTER JOIN t2 ON t1.id = t2.id};

結果:t1 所有列(2 列),t2 無匹配處顯示 NULL。

t1.idt1.valt2.idt2.val
1a1x
2bNULLNULL

5. 右外連接

MySQL 支援 RIGHT JOIN,語意與 LEFT JOIN 互換表順序。建議統一用 LEFT JOIN,閱讀習慣一致。

6. 自然連接

SELECT * FROM t1 NATURAL LEFT JOIN t2;

自動匹配同名欄位,不建議生產使用(Schema 變更易破壞)。

7. STRAIGHT_JOIN:強制連接順序

SELECT STRAIGHT_JOIN * FROM t1, t2 WHERE t1.id = t2.id;
-- 或 FROM 子句
SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.id = t2.id;

強制按 FROM 子句順序連接,繞過優化器重排。慎用,需配合 EXPLAIN 驗證確有收益。

三、欄位限定與別名規範

限定規則

  • 單表查詢:欄位名無歧義,可直接使用
  • 多表查詢:同名欄位必須加表名/別名前綴 tbl.col 或 alias.col

別名應用

-- 表別名
SELECT a.id, a.val, b.val AS b_val
FROM t1 AS a
LEFT JOIN t2 AS b ON a.id = b.id;

-- 自我連接(階層/遞迴結構)
SELECT e.name AS employee, m.name AS manager
FROM emp AS e
LEFT JOIN emp AS m ON e.manager_id = m.emp_id;

四、WHERE vs HAVING 過濾邏輯

特性WHEREHAVING
執行階段分組前、連接後分組後
可用聚合函數否是
可用別名否(標準 SQL)是
索引利用是否

實戰原則:能用 WHERE 過濾的盡量用 WHERE,HAVING 僅用於聚合條件(如 HAVING COUNT(*) > 5)。

五、GROUP BY 與 ONLY_FULL_GROUP_BY

MySQL 5.7+ 預設啟用 ONLY_FULL_GROUP_BY,要求 SELECT 清單中非聚合欄位必須出現在 GROUP BY 中。

-- 錯誤(嚴格模式)
SELECT customer_id, COUNT(*), MAX(amount) FROM orders GROUP BY customer_id;
-- 正確
SELECT customer_id, COUNT(*), MAX(amount) FROM orders GROUP BY customer_id, MAX(amount);
-- 或使用 ANY_VALUE()
SELECT customer_id, COUNT(*), ANY_VALUE(MAX(amount)) FROM orders GROUP BY customer_id;

六、實戰解決方案模式庫

模式 1:找出左表有、右表無的列(差集)

SELECT t1.* FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL;

模式 2:分組取每組前 N 列(MySQL 8.0+ 窗口函數)

WITH ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY category ORDER BY score DESC) AS rn
  FROM scores
)
SELECT * FROM ranked WHERE rn <= 3;

舊版本:GROUP_CONCAT + 應用層分割、或相關子查詢(效能差)。

模式 3:分頁優化(深分頁問題)

-- 低效:OFFSET 掃描大量列
SELECT * FROM orders ORDER BY created_at DESC LIMIT 100000, 10;

-- 高效:游標式分頁(需唯一排序鍵)
SELECT * FROM orders 
WHERE created_at < '2024-01-15 10:00:00'  -- 上一頁最後一筆時間
ORDER BY created_at DESC LIMIT 10;

模式 4:UPSERT(INSERT ... ON DUPLICATE KEY UPDATE)

INSERT INTO stats (date, counter) VALUES ('2024-01-15', 1)
ON DUPLICATE KEY UPDATE counter = counter + 1;

模式 5:多表同步刪除/更新

-- 刪除訂單及其明細
DELETE o, d FROM orders o
JOIN order_details d ON o.id = d.order_id
WHERE o.created_at < '2023-01-01';

-- 更新主表統計欄位
UPDATE orders o
JOIN (
  SELECT order_id, SUM(amount) AS total
  FROM order_details GROUP BY order_id
) d ON o.id = d.order_id
SET o.total_amount = d.total;

七、子查詢 vs 連接:效能抉擇

場景推薦理由
子查詢回傳單值(標量)子查詢可讀性佳,優化器常轉為連接
IN/EXISTS 子查詢EXISTS / JOINEXISTS 半連接優化,IN 早期版本效能差
FROM 子查詢(衍生表)避免 / CTE / 視圖物化暫存表無索引,5.6+ 支援衍生表合併
相關子查詢改寫為 JOIN逐列執行,效能極差

八、LIMIT 進階用法

  • LIMIT 10:前 10 列
  • LIMIT 10, 20:跳過 10 列,取 20 列(OFFSET 10 LIMIT 20)
  • LIMIT 0, 10:等同 LIMIT 10
  • 配合 ORDER BY 確保結果確定性
  • 深分頁必用游標式,避免 OFFSET 掃描代價

結語

檢索資料的藝術在於用最精準的連接類型表達業務邏輯、用最早的 WHERE 過濾削減資料集、用最合適的索引支援存取路徑、用最確定的 ORDER BY 保證分頁穩定。建立「先寫 SQL 邏輯、再看 EXPLAIN、最後調型別/索引/寫法」的開發習慣,並掌握上述解決方案模式庫,可應對 90% 以上的查詢場景。MySQL 8.0 引入 CTE、窗口函數、側向連接,更將複雜查詢的表達力提升至新高度——升級版本、學習新語法,是持續提升檢索能力的必經之路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved