MySQL DQL從基礎查詢到實戰(zhàn)優(yōu)化全指南
MySQL DQL 完全指南:從基礎查詢到實戰(zhàn)優(yōu)化
DQL(數據查詢語言)是 SQL 中最常用、最核心的部分 ——80% 的數據庫操作都是 “查詢”。無論是業(yè)務報表、數據分析還是頁面展示,都離不開SELECT語句。但很多開發(fā)者寫查詢時只追求 “能查出結果”,卻忽視了效率和可讀性,導致 “查詢慢”“邏輯亂” 等問題。本文從基礎查詢到復雜分組,再到執(zhí)行順序和規(guī)范,系統(tǒng)拆解 DQL 的核心知識點,幫你寫出 “既正確又高效” 的查詢語句。
一、DQL 核心概念與通用規(guī)范
1. 什么是 DQL?
DQL(Data Query Language)是用于從表中查詢數據的 SQL 語句,核心命令只有一個:SELECT。它不修改數據,只返回結果集,是業(yè)務開發(fā)中使用頻率最高的 SQL 類型。
2. 通用語法框架
所有查詢語句都遵循以下基本結構(按執(zhí)行順序排列,而非書寫順序):
SELECT [DISTINCT] 字段列表 -- 5. 確定返回哪些字段 FROM 表名 -- 1. 確定查詢的表 [WHERE 條件] -- 2. 篩選行(分組前) [GROUP BY 分組字段] -- 3. 按字段分組 [HAVING 分組條件] -- 4. 篩選分組(分組后) [ORDER BY 排序字段 [ASC/DESC]] -- 6. 排序 [LIMIT 起始位置, 條數]; -- 7. 分頁(限制返回條數)
3. 通用規(guī)范(提升可讀性和效率)
- 字段明確化:禁止用SELECT *(冗余字段拖慢速度,表結構變更易出錯),需指定具體字段;
- 關鍵字大寫:SELECT、FROM等關鍵字大寫,字段名 / 表名小寫,區(qū)分清晰;
- 格式對齊:多條件 / 多字段時換行對齊(示例見下文),避免一行堆到底;
- 注釋說明:復雜查詢加注釋,說明查詢目的(如 “統(tǒng)計各部門月均薪資”);
- 優(yōu)先索引:WHERE、GROUP BY、ORDER BY的字段盡量建索引(加速查詢)。
二、基礎查詢:獲取數據的第一步
基礎查詢是所有復雜查詢的基礎,核心是 “明確要查哪些字段”。
1. 語法與案例
(1)查詢指定字段
-- 語法:SELECT 字段1, 字段2 FROM 表名; SELECT emp_id, emp_name, salary FROM employee; -- 查員工的ID、姓名、薪資
(2)查詢所有字段(不推薦,僅臨時調試用)
SELECT * FROM employee; -- 查所有字段(生產環(huán)境禁止?。?
問題:返回冗余字段(如無需展示的create_time),表加新字段后會自動返回,可能導致業(yè)務異常。
(3)去重查詢(DISTINCT)
-- 語法:SELECT DISTINCT 字段 FROM 表名; -- 去除字段重復值 SELECT DISTINCT dept_id FROM employee; -- 查所有有員工的部門ID(去重)
注意:DISTINCT作用于其后所有字段(如DISTINCT a,b會同時去重 a 和 b 的組合)。
(4)別名查詢(AS)
用別名簡化字段名或表名,提升可讀性:
-- 語法:字段/表名 [AS] 別名(AS可省略) SELECT emp_id AS 員工ID, emp_name 姓名, -- 省略AS salary * 12 年薪 -- 表達式也可加別名 FROM employee e; -- 表別名e(后續(xù)可簡寫)
三、條件查詢:篩選符合要求的數據
實際業(yè)務中很少查全表數據,而是按條件篩選(如 “查薪資> 10000 的員工”),WHERE子句是條件查詢的核心。
1. 常用條件運算符
| 類型 | 運算符 / 關鍵字 | 說明 |
|---|---|---|
| 比較運算 | =、!=、>、<、>=、<= | 基本比較(如salary > 10000) |
| 邏輯運算 | AND、OR、NOT | 多條件組合(如salary > 8000 AND dept_id=1) |
| 范圍查詢 | BETWEEN … AND … | 在指定范圍內(如age BETWEEN 20 AND 30) |
| 集合查詢 | IN (值1, 值2…) | 在指定集合中(如dept_id IN (1,2)) |
| 模糊查詢 | LIKE | 匹配字符串(%通配任意字符,_通配單個字符) |
| 空值查詢 | IS NULL / IS NOT NULL | 判斷是否為空(如dept_id IS NULL) |
2. 實戰(zhàn)案例
-- 案例1:查研發(fā)部(dept_id=1)薪資>10000的員工 SELECT emp_name, salary FROM employee WHERE dept_id = 1 AND salary > 10000; -- 案例2:查年齡在25-35歲之間(包含25和35)的員工 SELECT emp_name, age FROM employee WHERE age BETWEEN 25 AND 35; -- 等價于 age >=25 AND age <=35 -- 案例3:查部門ID為1、2、3的員工(用IN替代多個OR) SELECT emp_name, dept_id FROM employee WHERE dept_id IN (1, 2, 3); -- 比 dept_id=1 OR dept_id=2 更簡潔 -- 案例4:查姓名以“張”開頭的員工(模糊查詢) SELECT emp_name FROM employee WHERE emp_name LIKE '張%'; -- %匹配任意字符(如“張三”“張三豐”) -- 案例5:查沒有部門(dept_id為空)的員工 SELECT emp_name FROM employee WHERE dept_id IS NULL; -- 注意:不能用 = NULL(NULL需用IS判斷)
3. 條件查詢規(guī)范
- 多條件優(yōu)先用AND/OR,避免嵌套過深(超過 3 層建議拆分);
- 范圍判斷優(yōu)先用BETWEEN(比>=+<=更簡潔);
- 模糊查詢慎用%開頭(如LIKE ‘%張’,會導致索引失效,查詢變慢)。
四、聚合函數:對數據做統(tǒng)計分析
聚合函數用于 “匯總數據”(如 “計算平均薪資”“統(tǒng)計員工總數”),常與GROUP BY配合使用。
1. 常用聚合函數
| 函數 | 說明 | 示例 |
|---|---|---|
| COUNT() | 統(tǒng)計行數(非 NULL 值的數量) | COUNT(emp_id) 統(tǒng)計有效員工數 |
| SUM() | 求和(僅數值類型) | SUM(salary) 計算總薪資 |
| AVG() | 求平均值(僅數值類型) | AVG(salary) 計算平均薪資 |
| MAX() | 求最大值 | MAX(salary) 查最高薪資 |
| MIN() | 求最小值 | MIN(hire_date) 查最早入職日期 |
2. 實戰(zhàn)案例
-- 案例1:統(tǒng)計員工總數(COUNT(*)包含NULL,COUNT(字段)排除NULL) SELECT COUNT(*) AS 總記錄數, -- 包含所有行(包括字段為NULL的) COUNT(emp_id) AS 有效員工數 -- 僅統(tǒng)計emp_id非NULL的行(主鍵不會NULL) FROM employee; -- 案例2:計算研發(fā)部(dept_id=1)的薪資總和、平均值、最高值 SELECT SUM(salary) AS 總薪資, AVG(salary) AS 平均薪資, MAX(salary) AS 最高薪資 FROM employee WHERE dept_id = 1; -- 先篩選研發(fā)部,再聚合
3. 聚合函數注意事項
- COUNT(*) 統(tǒng)計所有行(包括 NULL),COUNT(字段) 統(tǒng)計該字段非 NULL 的行;
- 聚合函數會自動忽略NULL值(如SUM(salary) 不會計算salary為 NULL 的行);
- 不能在WHERE中使用聚合函數(如WHERE AVG(salary) > 8000 錯誤,需用HAVING)。
五、分組查詢:按類別匯總數據
分組查詢(GROUP BY)用于 “按某個字段分類統(tǒng)計”(如 “按部門統(tǒng)計員工數”),常與聚合函數配合。
1. 語法與案例
-- 基礎語法:GROUP BY 分組字段 [HAVING 分組條件] -- 案例1:按部門分組,統(tǒng)計每個部門的員工數和平均薪資 SELECT dept_id AS 部門ID, COUNT(emp_id) AS 員工數, -- 每個部門的員工數 AVG(salary) AS 平均薪資 -- 每個部門的平均薪資 FROM employee GROUP BY dept_id; -- 按部門ID分組 -- 案例2:分組后篩選(HAVING):平均薪資>9000的部門 SELECT dept_id AS 部門ID, COUNT(emp_id) AS 員工數, AVG(salary) AS 平均薪資 FROM employee GROUP BY dept_id HAVING 平均薪資 > 9000; -- 篩選分組后的結果(用別名更簡潔)
2. WHERE vs HAVING(核心區(qū)別)
| 子句 | 作用時機 | 能否用聚合函數 | 典型場景 |
|---|---|---|---|
| WHERE | 分組前篩選行 | 不能 | 篩選單個字段(如dept_id=1) |
| HAVING | 分組后篩選組 | 能 | 篩選聚合結果(如AVG(salary)>9000) |
示例對比:
-- 先篩選2022年后入職的員工,再按部門分組統(tǒng)計平均薪資>8000的部門 SELECT dept_id, AVG(salary) AS 平均薪資 FROM employee WHERE hire_date >= '2022-01-01' -- 分組前:只留2022年后入職的 GROUP BY dept_id HAVING 平均薪資 > 8000; -- 分組后:只留平均薪資超8000的部門
六、排序查詢:按規(guī)則排列結果
查詢結果默認無序,ORDER BY用于按指定字段排序(如 “按薪資從高到低排列”)。
1. 語法與案例
-- 基礎語法:ORDER BY 字段1 [ASC/DESC], 字段2 [ASC/DESC] -- ASC:升序(默認,可省略);DESC:降序 -- 案例1:按薪資降序排列(從高到低) SELECT emp_name, salary FROM employee ORDER BY salary DESC; -- 案例2:多字段排序:先按部門ID升序,再按薪資降序 SELECT emp_name, dept_id, salary FROM employee ORDER BY dept_id ASC, salary DESC; -- 部門相同則比薪資
2. 排序規(guī)范
- 字符串排序按字符編碼順序(如中文按拼音,需注意數據庫字符集);
- 大表排序加索引(ORDER BY的字段建索引,避免全表掃描排序);
- 分頁前必須排序(否則分頁結果可能混亂,如第 1 頁和第 2 頁有重復數據)。
七、分頁查詢:限制返回結果條數
當數據量很大時(如 10 萬條),需分頁查詢(如 “每頁顯示 10 條”),LIMIT是實現分頁的核心。
1. 語法與案例
-- 語法:LIMIT 起始位置, 每頁條數(起始位置從0開始) -- 計算方式:第N頁的起始位置 = (N-1) * 每頁條數 -- 案例1:查詢第1頁數據(每頁10條,起始位置0) SELECT emp_id, emp_name FROM employee ORDER BY emp_id ASC -- 分頁必須先排序,保證順序一致 LIMIT 0, 10; -- 案例2:查詢第2頁數據(起始位置10,取10條) SELECT emp_id, emp_name FROM employee ORDER BY emp_id ASC LIMIT 10, 10;
2. 分頁規(guī)范
- 分頁必加ORDER BY(否則每次查詢的 “第 1 頁” 可能不同);
- 大表分頁優(yōu)化:用主鍵范圍替代LIMIT(如WHERE emp_id > 100 LIMIT 10,比LIMIT 100,10快);
- 前端傳遞 “頁碼” 和 “每頁條數”,后端計算起始位置(避免前端傳錯)。
八、案例練習:綜合查詢實戰(zhàn)
結合以上所有知識點,實現一個 “多條件統(tǒng)計 + 排序 + 分頁” 的綜合查詢:
需求:查詢研發(fā)部(dept_id=1)2022 年后入職的員工,按薪資降序排列,統(tǒng)計每個薪資段的人數,只看人數≥2 的薪資段,最后取第 1 頁(每頁 5 條)。
-- 分步拆解: -- 1. 篩選研發(fā)部+2022年后入職(WHERE) -- 2. 按薪資段分組(GROUP BY) -- 3. 篩選人數≥2的組(HAVING) -- 4. 按人數降序(ORDER BY) -- 5. 分頁取第1頁(LIMIT) SELECT FLOOR(salary / 1000) * 1000 AS 薪資段, -- 按1000為單位分組(如8000-8999) COUNT(emp_id) AS 人數 FROM employee WHERE dept_id = 1 AND hire_date >= '2022-01-01' GROUP BY 薪資段 HAVING 人數 >= 2 ORDER BY 人數 DESC LIMIT 0, 5;
九、DQL 執(zhí)行順序:理解查詢的 “幕后流程”
很多人困惑 “為什么WHERE不能用聚合函數”“別名在哪個階段生效”,答案在執(zhí)行順序里。DQL 各部分的執(zhí)行順序如下(與書寫順序不同):
- FROM:確定查詢的表;
- WHERE:篩選行(分組前);
- GROUP BY:按字段分組;
- HAVING:篩選分組(分組后);
- SELECT:確定返回的字段和別名;
- ORDER BY:按字段或別名排序(此時已能識別SELECT中的別名);
- LIMIT:分頁限制返回條數。
舉例說明:
SELECT salary12 AS 年薪 FROM employee WHERE 年薪 > 100000 會報錯 —— 因為WHERE在SELECT之前執(zhí)行,此時 “年薪” 別名還未生成。正確寫法是WHERE salary12 > 100000。
十、DQL 小結:核心要點與規(guī)范總覽
1. 核心操作清單
| 操作類型 | 關鍵字 / 語法 | 核心作用 | 注意事項 |
|---|---|---|---|
| 基礎查詢 | SELECT 字段 FROM 表 | 獲取指定字段數據 | 禁止SELECT *,用別名簡化 |
| 條件查詢 | WHERE 條件 | 篩選符合條件的行 | 支持AND/OR/BETWEEN/LIKE等 |
| 聚合查詢 | COUNT()/SUM()/AVG()等 | 統(tǒng)計匯總數據 | 忽略 NULL,WHERE中不能用 |
| 分組查詢 | GROUP BY 字段 [HAVING 條件] | 按類別統(tǒng)計 | HAVING用于篩選分組結果 |
| 排序查詢 | ORDER BY 字段 [ASC/DESC] | 按規(guī)則排列結果 | 大表加索引,分頁前必排序 |
| 分頁查詢 | LIMIT 起始位置, 條數 | 限制返回條數,實現分頁 | 起始位置從 0 開始,需配合ORDER BY |
2. 規(guī)范與最佳實踐
- 性能優(yōu)化:
- 只查需要的字段(避免SELECT *);
- WHERE/GROUP BY/ORDER BY的字段建索引;
- 避免LIMIT大偏移量(如LIMIT 100000, 10,改用主鍵范圍)。
- 可讀性:
- 多字段 / 多條件換行對齊;
- 復雜查詢加注釋說明業(yè)務目的;
- 表和字段用別名簡化(如e代表employee)。
- 正確性:
- 分頁必加ORDER BY;
- 分組查詢中,SELECT只能包含分組字段和聚合函數;
- 模糊查詢慎用%開頭(防止索引失效)。
DQL 是 SQL 的 “靈魂”,掌握它不僅能完成業(yè)務需求,更能通過優(yōu)化查詢提升系統(tǒng)性能。記?。簩懖樵儠r多思考 “是否有更高效的方式”“別人能否看懂”,養(yǎng)成規(guī)范習慣,才能從 “會查” 變成 “查得好”。
到此這篇關于MySQL DQL 完全指南:從基礎查詢到實戰(zhàn)優(yōu)化的文章就介紹到這了,更多相關mysql dql內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
MYSQL 高級文本查詢之regexp_like和REGEXP詳解
在MySQL中,regexp_like和REGEXP都是用于執(zhí)行正則表達式搜索的函數,這篇文章主要介紹了MYSQL 高級文本查詢之regexp_like和REGEXP,需要的朋友可以參考下2023-05-05

