SQL 語法大全:SELECT、JOIN、WHERE 完整查詢指令教學【2025】
SQL 語法大全:SELECT、JOIN、WHERE 完整查詢指令教學【2025】
引言:掌握 SQL 語法的重要性
你有沒有想過,為什麼資料分析師的履歷上幾乎都寫著「熟悉 SQL」?
答案很簡單:SQL 是與資料庫溝通的共通語言。無論你使用 MySQL、PostgreSQL 還是 SQL Server,核心語法都是相通的。
這篇文章將系統性地介紹 SQL 查詢語法的每一個環節。從最基本的 SELECT 開始,到 WHERE 條件篩選、JOIN 多表連接,再到 GROUP BY 分組統計。讀完這篇,你就能寫出涵蓋 90% 日常需求的 SQL 查詢。
如果你是完全的新手,建議先閱讀 SQL 完整指南:從入門到精通 了解基本概念。

SQL 查詢語法概觀
SQL 語句的基本結構
一個完整的 SQL 查詢語句通常包含以下子句:
SELECT 欄位 -- 1. 選取要顯示的欄位
FROM 資料表 -- 2. 指定資料來源
WHERE 條件 -- 3. 篩選資料(可選)
GROUP BY 分組欄位 -- 4. 分組統計(可選)
HAVING 分組條件 -- 5. 篩選分組結果(可選)
ORDER BY 排序欄位 -- 6. 排序結果(可選)
LIMIT 筆數 -- 7. 限制回傳筆數(可選)
SQL 執行順序
這是很多人搞混的地方:SQL 的撰寫順序和執行順序不同。
執行順序(重要!):
- FROM → 決定資料來源
- WHERE → 篩選個別資料列
- GROUP BY → 進行分組
- HAVING → 篩選分組結果
- SELECT → 選取要顯示的欄位
- ORDER BY → 排序
- LIMIT → 限制筆數
理解執行順序能幫助你避免很多錯誤。例如,你不能在 WHERE 中使用 SELECT 定義的別名,因為 WHERE 比 SELECT 先執行。
SQL 語法分類
SQL 語法依功能分為四大類:
| 類別 | 全名 | 常用指令 | 用途 |
|---|---|---|---|
| DQL | Data Query Language | SELECT | 查詢資料 |
| DML | Data Manipulation Language | INSERT、UPDATE、DELETE | 操作資料 |
| DDL | Data Definition Language | CREATE、ALTER、DROP | 定義結構 |
| DCL | Data Control Language | GRANT、REVOKE | 權限控制 |
本文主要聚焦在 DQL(查詢語言),這也是日常使用最頻繁的部分。
想了解 DML 操作,請參考 SQL CRUD 操作完整指南。
SELECT 查詢語法完整解析
基本 SELECT 結構
SELECT 是 SQL 最核心的指令,用來從資料表中擷取資料。
最簡單的查詢:
-- 查詢所有欄位
SELECT * FROM employees;
-- 查詢特定欄位
SELECT name, department, salary FROM employees;
重要提醒:在正式環境中避免使用 SELECT *,原因有三:
- 效能較差(讀取不需要的欄位)
- 欄位順序可能變動
- 程式碼可讀性較低
欄位別名 AS
使用 AS 可以為欄位或資料表設定別名,讓結果更易讀。
-- 欄位別名
SELECT
name AS 員工姓名,
salary AS 月薪,
salary * 12 AS 年薪
FROM employees;
-- AS 可以省略(但建議保留以提高可讀性)
SELECT name 員工姓名, salary 月薪 FROM employees;
DISTINCT 去除重複
DISTINCT 用來移除重複的資料列。
-- 查詢所有不重複的部門
SELECT DISTINCT department FROM employees;
-- 多欄位去重(組合後不重複)
SELECT DISTINCT department, job_title FROM employees;
注意:DISTINCT 會對所有選取的欄位進行去重判斷,而非單一欄位。
計算欄位與運算
SELECT 中可以進行數學運算和字串處理。
-- 數學運算
SELECT
name,
salary,
salary * 1.05 AS 調薪後月薪,
salary * 14 AS 年薪含獎金
FROM employees;
-- 字串連接(SQL Server)
SELECT
name + ' - ' + department AS 員工資訊
FROM employees;
-- 字串連接(MySQL)
SELECT
CONCAT(name, ' - ', department) AS 員工資訊
FROM employees;
WHERE 條件篩選技巧
比較運算子
WHERE 子句用來篩選符合條件的資料列。
| 運算子 | 說明 | 範例 |
|---|---|---|
| = | 等於 | WHERE status = 'active' |
| <> 或 != | 不等於 | WHERE status <> 'inactive' |
| > | 大於 | WHERE salary > 50000 |
| < | 小於 | WHERE age < 30 |
| >= | 大於等於 | WHERE score >= 60 |
| <= | 小於等於 | WHERE price <= 1000 |
-- 查詢薪資超過 60000 的員工
SELECT name, salary
FROM employees
WHERE salary > 60000;
-- 查詢非行銷部的員工
SELECT name, department
FROM employees
WHERE department <> '行銷部';
LIKE 模糊查詢
LIKE 用於字串的模糊比對,搭配萬用字元使用。
| 萬用字元 | 說明 | 範例 |
|---|---|---|
| % | 任意多個字元 | '王%' 匹配「王小明」「王大偉」 |
| _ | 單一字元 | '王_明' 匹配「王小明」但不匹配「王大明明」 |
-- 查詢姓王的員工
SELECT * FROM employees WHERE name LIKE '王%';
-- 查詢名字第二個字是「小」的員工
SELECT * FROM employees WHERE name LIKE '_小%';
-- 查詢 email 是 gmail 的員工
SELECT * FROM employees WHERE email LIKE '%@gmail.com';
-- 查詢職稱包含「工程師」的員工
SELECT * FROM employees WHERE job_title LIKE '%工程師%';
IN 與 NOT IN 列表查詢
IN 用來比對一組值,比多個 OR 更簡潔。
-- 查詢台北、台中、高雄的客戶
SELECT * FROM customers
WHERE city IN ('台北', '台中', '高雄');
-- 等同於
SELECT * FROM customers
WHERE city = '台北' OR city = '台中' OR city = '高雄';
-- 排除特定部門
SELECT * FROM employees
WHERE department NOT IN ('人資部', '財務部');
BETWEEN 範圍查詢
BETWEEN 用於範圍查詢,包含起始和結束值。
-- 查詢薪資在 40000 到 60000 之間的員工
SELECT name, salary
FROM employees
WHERE salary BETWEEN 40000 AND 60000;
-- 等同於
SELECT name, salary
FROM employees
WHERE salary >= 40000 AND salary <= 60000;
-- 日期範圍查詢
SELECT * FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31';
IS NULL 空值處理
NULL 表示「沒有值」,不能用 = 來比較。
-- 查詢沒有填寫 email 的員工
SELECT * FROM employees WHERE email IS NULL;
-- 查詢有填寫 email 的員工
SELECT * FROM employees WHERE email IS NOT NULL;
-- 錯誤寫法(永遠不會有結果)
SELECT * FROM employees WHERE email = NULL; -- ❌
重要觀念:NULL 不等於空字串 '',也不等於 0。NULL 代表「未知」或「不存在」。
邏輯運算子 AND、OR、NOT
組合多個條件時使用邏輯運算子。
-- AND:兩個條件都要成立
SELECT * FROM employees
WHERE department = '工程部' AND salary > 70000;
-- OR:至少一個條件成立
SELECT * FROM employees
WHERE department = '工程部' OR department = '產品部';
-- NOT:反轉條件
SELECT * FROM employees
WHERE NOT (salary < 50000);
-- 複合條件(注意括號優先順序)
SELECT * FROM employees
WHERE (department = '工程部' OR department = '產品部')
AND salary > 60000;

需要系統化學習 SQL?
根據調查,系統化學習 SQL 的人比自學摸索的人平均節省 60% 的學習時間,且更不容易遺漏重要觀念。
免費 SQL 語法速查表
我們整理了一份完整的 SQL 語法速查表 PDF,包含:
- SELECT 完整語法結構
- 所有比較運算子與範例
- JOIN 類型圖解
- 常用函數清單
- 效能優化提示
這份速查表可以列印出來放在桌邊,隨時查閱。
CloudInsight SQL 培訓服務
如果你的團隊需要系統化的 SQL 培訓,CloudInsight 提供:
- 客製化課程:依團隊程度設計課程內容
- 實戰導向:使用真實資料進行練習
- 課後支援:提供 30 天線上問答服務
聚合函數與 GROUP BY
五大聚合函數
聚合函數對一組資料進行計算,回傳單一結果。
| 函數 | 功能 | 範例 | 注意事項 |
|---|---|---|---|
| COUNT() | 計算筆數 | COUNT(*) | COUNT(*) 包含 NULL,COUNT(欄位) 不含 |
| SUM() | 加總 | SUM(salary) | 只能用於數值欄位 |
| AVG() | 平均值 | AVG(score) | 自動忽略 NULL |
| MAX() | 最大值 | MAX(price) | 可用於字串(依字母排序) |
| MIN() | 最小值 | MIN(age) | 可用於日期 |
-- 統計員工總數
SELECT COUNT(*) AS 員工總數 FROM employees;
-- 計算平均薪資
SELECT AVG(salary) AS 平均薪資 FROM employees;
-- 多個聚合函數同時使用
SELECT
COUNT(*) AS 員工數,
SUM(salary) AS 薪資總和,
AVG(salary) AS 平均薪資,
MAX(salary) AS 最高薪資,
MIN(salary) AS 最低薪資
FROM employees;
GROUP BY 分組統計
GROUP BY 將資料依指定欄位分組,再對每組進行聚合計算。
-- 計算各部門的員工人數和平均薪資
SELECT
department,
COUNT(*) AS 員工人數,
AVG(salary) AS 平均薪資
FROM employees
GROUP BY department;
-- 多欄位分組
SELECT
department,
job_title,
COUNT(*) AS 人數
FROM employees
GROUP BY department, job_title;
重要規則:SELECT 中的非聚合欄位,必須出現在 GROUP BY 中。
-- ❌ 錯誤:name 不在 GROUP BY 中
SELECT department, name, COUNT(*)
FROM employees
GROUP BY department;
-- ✅ 正確
SELECT department, COUNT(*)
FROM employees
GROUP BY department;
HAVING 分組條件
HAVING 用來篩選分組後的結果,不能用 WHERE 替代。
-- 找出員工人數超過 5 人的部門
SELECT department, COUNT(*) AS 員工人數
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;
-- 找出平均薪資超過 60000 的部門
SELECT department, AVG(salary) AS 平均薪資
FROM employees
GROUP BY department
HAVING AVG(salary) > 60000;
WHERE vs HAVING 差異
這是常見的面試考題,務必搞清楚。
| 比較項目 | WHERE | HAVING |
|---|---|---|
| 執行時機 | GROUP BY 之前 | GROUP BY 之後 |
| 篩選對象 | 個別資料列 | 分組結果 |
| 能否使用聚合函數 | 不能 | 可以 |
-- 先用 WHERE 篩選資料,再分組統計
SELECT department, AVG(salary) AS 平均薪資
FROM employees
WHERE hire_date >= '2020-01-01' -- 篩選 2020 年後入職的員工
GROUP BY department
HAVING AVG(salary) > 50000; -- 篩選平均薪資超過 50000 的部門
排序與分頁
ORDER BY 排序
ORDER BY 用來對結果進行排序。
-- 依薪資由高到低排序
SELECT name, salary
FROM employees
ORDER BY salary DESC;
-- 依薪資由低到高排序(ASC 是預設值,可省略)
SELECT name, salary
FROM employees
ORDER BY salary ASC;
-- 多欄位排序
SELECT name, department, salary
FROM employees
ORDER BY department ASC, salary DESC;
-- 先依部門升序,同部門內再依薪資降序
排序關鍵字:
- ASC:升序(Ascending),由小到大,預設值
- DESC:降序(Descending),由大到小
LIMIT 與 OFFSET 分頁
LIMIT 限制回傳的資料筆數,常用於分頁。
-- 取前 10 筆(MySQL、PostgreSQL、SQLite)
SELECT * FROM employees LIMIT 10;
-- 取第 11-20 筆(跳過前 10 筆)
SELECT * FROM employees LIMIT 10 OFFSET 10;
-- 簡寫語法(MySQL)
SELECT * FROM employees LIMIT 10, 10; -- LIMIT 偏移量, 筆數
SQL Server 的分頁語法不同:
-- SQL Server 2012+
SELECT * FROM employees
ORDER BY id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
-- SQL Server 較舊版本
SELECT TOP 10 * FROM employees;
分頁查詢範例
實務上的分頁通常這樣實作:
-- 假設每頁顯示 20 筆,查詢第 3 頁
-- 第 3 頁 = 跳過前 40 筆((3-1) * 20)
SELECT *
FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;
JOIN 多表連接概述
當資料分散在多個資料表時,需要用 JOIN 來合併。
JOIN 類型總覽
| JOIN 類型 | 說明 | 使用時機 |
|---|---|---|
| INNER JOIN | 只回傳兩邊都有匹配的資料 | 最常用,只要有關聯的資料 |
| LEFT JOIN | 回傳左表所有資料 | 要保留左表所有資料,即使右表沒有匹配 |
| RIGHT JOIN | 回傳右表所有資料 | 較少使用,可用 LEFT JOIN 改寫 |
| FULL OUTER JOIN | 回傳兩邊所有資料 | 需要兩表的完整聯集 |
| CROSS JOIN | 笛卡爾積 | 需要所有組合(較少用) |
INNER JOIN 基本範例
-- 查詢訂單及對應的客戶名稱
SELECT
orders.order_id,
orders.order_date,
customers.name AS customer_name
FROM orders
INNER JOIN customers ON orders.customer_id = customers.id;
-- 使用表格別名簡化
SELECT
o.order_id,
o.order_date,
c.name AS customer_name
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id;
LEFT JOIN 範例
-- 查詢所有客戶及其訂單(包含沒有訂單的客戶)
SELECT
c.name,
o.order_id,
o.total_amount
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id;
沒有訂單的客戶,order_id 和 total_amount 會顯示 NULL。
JOIN 是 SQL 進階查詢的核心技能,完整的圖解教學請參考 SQL JOIN 完整教學指南。

實戰範例與練習題
範例資料庫結構
假設我們有以下三個資料表:
employees(員工表)
| 欄位 | 類型 | 說明 |
|---|---|---|
| id | INT | 員工編號 |
| name | VARCHAR | 姓名 |
| department_id | INT | 部門編號 |
| salary | DECIMAL | 薪資 |
| hire_date | DATE | 入職日期 |
departments(部門表)
| 欄位 | 類型 | 說明 |
|---|---|---|
| id | INT | 部門編號 |
| name | VARCHAR | 部門名稱 |
| manager_id | INT | 主管編號 |
orders(訂單表)
| 欄位 | 類型 | 說明 |
|---|---|---|
| id | INT | 訂單編號 |
| employee_id | INT | 負責員工 |
| amount | DECIMAL | 訂單金額 |
| order_date | DATE | 訂單日期 |
練習題與解答
題目 1:查詢薪資前 5 高的員工姓名和薪資
SELECT name, salary
FROM employees
ORDER BY salary DESC
LIMIT 5;
題目 2:查詢各部門的員工人數和平均薪資
SELECT
d.name AS 部門名稱,
COUNT(e.id) AS 員工人數,
ROUND(AVG(e.salary), 0) AS 平均薪資
FROM departments d
LEFT JOIN employees e ON d.id = e.department_id
GROUP BY d.id, d.name;
題目 3:找出 2024 年訂單金額超過 100 萬的員工
SELECT
e.name,
SUM(o.amount) AS 總訂單金額
FROM employees e
INNER JOIN orders o ON e.id = o.employee_id
WHERE o.order_date BETWEEN '2024-01-01' AND '2024-12-31'
GROUP BY e.id, e.name
HAVING SUM(o.amount) > 1000000
ORDER BY 總訂單金額 DESC;
題目 4:查詢沒有任何訂單的員工
SELECT e.name
FROM employees e
LEFT JOIN orders o ON e.id = o.employee_id
WHERE o.id IS NULL;
SQL 語法速查表
SELECT 語法結構
SELECT [DISTINCT] 欄位1, 欄位2, ...
FROM 資料表
[JOIN 其他表 ON 條件]
[WHERE 篩選條件]
[GROUP BY 分組欄位]
[HAVING 分組條件]
[ORDER BY 排序欄位 [ASC|DESC]]
[LIMIT 筆數 [OFFSET 偏移量]]
常用運算子速查
| 類型 | 運算子 |
|---|---|
| 比較 | =, <>, >, <, >=, <= |
| 範圍 | BETWEEN...AND |
| 列表 | IN, NOT IN |
| 模糊 | LIKE (%, _) |
| 空值 | IS NULL, IS NOT NULL |
| 邏輯 | AND, OR, NOT |
聚合函數速查
| 函數 | 用途 |
|---|---|
| COUNT(*) | 計算所有列數 |
| COUNT(欄位) | 計算非 NULL 的列數 |
| SUM(欄位) | 數值加總 |
| AVG(欄位) | 數值平均 |
| MAX(欄位) | 最大值 |
| MIN(欄位) | 最小值 |
想學習更多 SQL 函數,請參考 SQL 函數完整指南。
常見問題 FAQ
Q1: SQL SELECT 可以選取所有欄位嗎?
可以,使用 SELECT * 會選取資料表中的所有欄位。但在正式環境中不建議這樣做,因為:(1)效能較差,會讀取不必要的資料;(2)如果資料表結構改變,可能導致程式出錯;(3)程式碼可讀性較低。建議明確列出需要的欄位。
Q2: WHERE 和 HAVING 有什麼差別?
WHERE 在 GROUP BY 之前執行,用來篩選個別資料列,不能使用聚合函數。HAVING 在 GROUP BY 之後執行,用來篩選分組結果,可以使用聚合函數。例如:WHERE salary > 50000(篩選個人薪資)vs HAVING AVG(salary) > 50000(篩選部門平均薪資)。
Q3: SQL GROUP BY 一定要配合聚合函數嗎?
不一定,但 GROUP BY 通常會搭配聚合函數使用才有意義。如果只是要去除重複資料,可以使用 DISTINCT。GROUP BY 的主要目的是將資料分組後進行統計計算,如果不使用聚合函數,每組只會回傳一筆資料,結果可能不如預期。
延伸閱讀
掌握基礎語法後,建議繼續學習以下主題:
基礎進階:
- SQL JOIN 完整教學:INNER、LEFT、RIGHT JOIN 圖解
- SQL CRUD 操作指南:INSERT、UPDATE、DELETE 語法
- SQL 函數完整指南:字串、日期、聚合函數總整理
進階技巧:
實務應用:
提升團隊 SQL 能力
一個熟練 SQL 的資料分析師,產出效率是初學者的 5-10 倍。投資團隊的 SQL 培訓,是提升整體生產力最有效的方式之一。
CloudInsight SQL 企業培訓
- 初階課程:SELECT、WHERE、JOIN、GROUP BY 完整教學
- 進階課程:子查詢、視窗函數、效能優化
- 實戰工作坊:使用真實商業資料進行練習
- 課後輔導:30 天線上問答支援
培訓成效保證
- 完課後立即能獨立撰寫 80% 日常查詢
- 提供課程錄影,可反覆複習
- 結業測驗通過率 95% 以上
參考資料
- Microsoft, "Transact-SQL Reference" (2024)
- MySQL Documentation, "SELECT Statement" (2024)
- PostgreSQL Documentation, "SQL Commands" (2024)
- W3Schools, "SQL Tutorial" (2024)
- SQLZoo, "SQL Teaching" (2024)
相關文章
SQL 完整指南:從入門到精通的資料庫查詢語言教學【2025最新】
完整 SQL 教學,涵蓋基礎語法、SELECT/JOIN/UPDATE 等查詢指令、SQL Server 安裝設定、SQL Injection 防範。從零開始學會資料庫操作,附練習題與範例程式碼。
SQL雲端 SQL 資料庫比較:Azure SQL、Cloud SQL、AWS RDS 完整評比【2025】
全面比較三大雲端 SQL 資料庫服務:Azure SQL Database、Google Cloud SQL、AWS RDS。涵蓋功能特色、高可用性、定價模式、遷移策略,幫助企業選擇最適合的雲端資料庫方案。
SQLSQL CRUD 操作完整指南:INSERT、UPDATE、DELETE 語法教學【2025】
系統性介紹 SQL 資料操作語言(DML)核心指令。涵蓋 INSERT 新增、UPDATE 更新、DELETE 刪除的完整語法,以及 TRUNCATE 差異比較、交易控制、常見錯誤提醒。