首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

SQL SELECT 查詢深度解析:從基礎語法到多表關聯、子查詢與分組聚合

     編輯:MySQL 綜合教學

前言

SELECT 是 SQL 中使用頻率最高、功能最豐富的語句。本文系統梳理 完整語法結構、別名與表達式、DISTINCT 去重、WHERE 條件構建、多表連接、子查詢、排序分頁、分組聚合,並針對易混淆點給出對比示例。

一、完整語法骨架

SELECT [ALL | DISTINCT]
    {* | table.* | [table.]col1 [AS alias1] [, [table.]col2 [AS alias2]] ...}
FROM table_name
[WHERE condition]
[GROUP BY col_list [HAVING condition]]
[ORDER BY col_list [ASC | DESC]]
[LIMIT [offset,] row_count]

二、列表達式與別名

  • SELECT name, price FROM products; — 顯式列出列,避免 SELECT * 造成網絡/IO 浪費。
  • SELECT name AS book_name, price AS book_price FROM products; — 別名建議加 AS 提升可讀性;別名含空格需單引號 'book name'。
  • SELECT 1+2*3, 8%5; — 純量表達式可直接計算,不依賴表。
  • SELECT name, price, price*0.7 AS 'discount price' FROM products WHERE id <= 15; — 列表達式可混用算術運算。

三、DISTINCT 作用範圍

SELECT DISTINCT price FROM products;          -- 單列去重
SELECT DISTINCT price, name FROM products;    -- 整行去重(price+name 組合唯一)

誤區:DISTINCT col1, col2 作用於 整行組合,而非單獨對 col1 去重。

四、WHERE 條件構建大全

分類操作符/語法示例
邏輯運算AND / &&WHERE id>10 AND status=1
OR / ||WHERE cat='A' OR cat='B'
NOT / !WHERE NOT (id>100)
比較運算=WHERE id=10
<=>(NULL 安全等值)WHERE col <=> NULL 等同 col IS NULL
!= / <>WHERE status!=0
< <= > >=WHERE price BETWEEN 10 AND 20
NULL 判斷IS NULL / IS NOT NULLWHERE mobile IS NULL
ISNULL(expr)函數形式,返回 1/0
範圍BETWEEN ... AND ...WHERE id BETWEEN 10 AND 20 含邊界
NOT BETWEEN ... AND ...WHERE id NOT BETWEEN 10 AND 20
集合IN (val1, val2...)WHERE id IN (5,10,15)
NOT IN (...)WHERE id NOT IN (5,10)
模糊匹配LIKE _(單字符) %(任意長度)WHERE name LIKE '%java%'
NOT LIKEWHERE name NOT LIKE '%java%'
REGEXP / RLIKEWHERE name REGEXP '^java'(以 java 開頭)

五、多表連接(JOIN)

1. 笛卡爾積陷阱

SELECT c.name, p.name FROM cats c, products p;  -- 無條件:c.rows * p.rows 行,無業務意義

2. 內連接(等值連接)

SELECT c.name, p.name, p.price
FROM cats c
JOIN products p ON c.id = p.cid;  -- 推薦 ANSI SQL-92 語法

3. 自連接

SELECT a.id, a.name, b.id, b.name
FROM cats a
JOIN cats b ON a.pid = b.id;  -- 同表不同別名

六、子查詢

-- 標量子查詢(返回單值)
SELECT * FROM products WHERE price > (SELECT AVG(price) FROM products);

-- 列子查詢(返回單列多行)
SELECT * FROM products WHERE cid IN (SELECT id FROM cats WHERE name LIKE 'j%');

-- 行子查詢(返回單行多列)
SELECT * FROM t1 WHERE (col1, col2) = (SELECT col1, col2 FROM t2 LIMIT 1);

七、排序與分頁

ORDER BY price DESC;           -- 降序
ORDER BY price ASC, id DESC;   -- 多鍵排序
LIMIT 10;                      -- 前 10 行
LIMIT 0, 10;                   -- 同義
LIMIT 10 OFFSET 20;            -- 第 3 頁(每頁 10 行)

八、分組聚合

SELECT cid,
       COUNT(*) AS cnt,
       SUM(price) AS total,
       AVG(price) AS avg_p,
       MAX(price) AS max_p,
       MIN(price) AS min_p
FROM products
GROUP BY cid
HAVING AVG(price) > 50;  -- HAVING 過濾分組結果,只能用聚合函數/分組列

關鍵差異:WHERE 過濾原始行(聚合前),HAVING 過濾分組後結果(聚合後)。


最佳實踐清單:

  1. 生產環境禁用 SELECT *,顯式列出所需列。
  2. 大表分頁避免 LIMIT 1000000, 20,改用「游標/Seek 分頁」(見本專欄「MySQL LIMIT 深度優化」一文)。
  3. GROUP BY 列必須出現在 SELECT 列表或聚合函數中(ONLY_FULL_GROUP_BY 模式下強制)。
  4. 子查詢優先改寫為 JOIN 或 EXISTS,尤其 IN (SELECT...) 在大數據量下性能隱患大。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved