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

SQL 查詢結果排序完全指南:ORDER BY 進階用法與性能優化

     編輯:MySQL 綜合教學

SQL 查詢結果排序完全指南:ORDER BY 進階用法與性能優化

ORDER BY 是 SQL 中唯一能保證結果集順序的子句。本文系統梳理升/降序、多列排序、表達式/別名/位置排序、非選擇列排序等核心用法,並給出索引優化建議。

基礎語法

SELECT col1, col2 FROM table_name
ORDER BY col1 [ASC|DESC], col2 [ASC|DESC] ...
  • ASC (默認):升序,數值小→大,字母 A→Z,日期早→晚。
  • DESC:降序,反之。
  • NULL 排序:大多數數據庫 NULL 排在最前 (升序) 或最後 (降序),可用 ORDER BY col IS NULL, col 顯式控制。

六大進階用法

1. 非選擇列排序:SELECT 不出現的列也能排序

SELECT name, salary FROM employees ORDER BY hire_date DESC;

只要列在表中存在即可,不必出現在 SELECT 列表。注意:配合 DISTINCT 或 GROUP BY 時,排序列必須出現在選擇列表/分組列中 (標準 SQL 要求)。

2. 表達式排序:按計算結果排序

SELECT price, quantity, price*quantity AS total FROM orders
ORDER BY price*quantity DESC;  -- 或 ORDER BY total DESC (別名)

支持算術運算、函數調用、CASE 表達式等。性能提示:表達式無法直接利用索引,考慮生成列 (Generated Column) 或函數索引 (MySQL 8.0+)。

3. 別名排序:SELECT 列別名可用於 ORDER BY

SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users
ORDER BY full_name;

邏輯執行順序中 SELECT (含別名定義) 先於 ORDER BY,故可用。不可用於 WHERE/GROUP BY/HAVING。

4. 位置排序:按 SELECT 列表位置編號 (1-based)

SELECT dept_id, emp_id, salary FROM employees
ORDER BY 1 ASC, 2 ASC;  -- 先按第1列 dept_id,再按第2列 emp_id

優點:簡潔,UNION 查詢各子查詢列名不一致時必須用位置。缺點:可讀性差,維護易出錯 (增減列導致位置偏移)。建議僅用於臨時調試或 UNION 場景。

5. 多列排序:複合排序邏輯

SELECT * FROM employees
ORDER BY department_id ASC, salary DESC, hire_date ASC;

規則:先按第一列排序;第一列值相同的行,按第二列排序;以此類推。等同於複合索引 (department_id, salary DESC, hire_date) 的順序掃描。

6. 異構排序:COLLATE 指定排序規則

SELECT name FROM users ORDER BY name COLLATE utf8mb4_bin;  -- 二進制區分大小寫
SELECT name FROM users ORDER BY name COLLATE utf8mb4_general_ci; -- 不區分大小寫

解決字符集/校對規則導致的排序不符預期問題。

性能優化:讓 ORDER BY 用上索引

場景能否用索引優化建議
ORDER BY 索引列,方向一致✅ Index Scan建立對應方向索引
ORDER BY 索引列,方向混合✅ (MySQL 8.0+)建立混合方向索引 INDEX (a ASC, b DESC)
WHERE + ORDER BY 同索引列✅ 最優複合索引 (where_col, order_col)
ORDER BY 非索引列 / 表達式❌ Filesort增加索引、生成列、或接受 Filesort (小結果集可忍受)
JOIN 查詢 ORDER BY 驅動表列✅ 可能驅動表排序列有索引,優化器可用 Index Scan 避免臨時表
LIMIT 小值 + ORDER BY✅ 優先隊列MySQL 使用 Priority Queue 優化,極快

EXPLAIN 關鍵標識

  • Using filesort:需額外排序操作 (內存/磁盤臨時表),性能開銷大。
  • Using index:覆蓋索引,無需回表。
  • Using temporary; Using filesort:同時用臨時表和排序,典型於 GROUP BY + ORDER BY 列不一致。

避坑清單

  1. 大數據集無索引排序 → 磁盤臨時表 → 查詢超時。必加 LIMIT 或建索引。
  2. ORDER BY RAND() 隨機抽樣 → 全表掃描 + 臨時表排序,極慢。替代方案:WHERE id >= (SELECT FLOOR(RAND() * (MAX(id)-MIN(id)+1)) + MIN(id)) LIMIT 1。
  3. 分頁深翻頁 LIMIT 1000000, 20 + ORDER BY → 掃描 100萬行丟棄。優化:WHERE id > last_seen_id ORDER BY id LIMIT 20 (游標分頁)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved