SQL ORDER BY 支援多欄位排序,只需用逗號分隔,每欄位可獨立指定 ASC (升序) 或 DESC (降序)。本文詳細說明語法規則、優先級邏輯、NULL 值排序行為與跨資料庫差異,並提供實戰常見模式。
基本語法
SELECT col1, col2, col3
FROM t1
ORDER BY col1 DESC, col2 ASC, col3 DESC;
- 按
col1 降序排序
col1 相同者,按 col2 升序
- 前兩者皆相同者,按
col3 降序
- 省略
ASC/DESC 預設 ASC
等價寫法對比
-- 寫法 1:簡潔 (f1 升序、f2 降序)
ORDER BY f1, f2 DESC
-- 寫法 2:明確 (推薦,可讀性佳)
ORDER BY f1 ASC, f2 DESC
-- 寫法 3:雙降序 (必須各自指定 DESC)
ORDER BY f1 DESC, f2 DESC
NULL 值排序行為 (關鍵差異)
| 資料庫 | ASC (升序) | DESC (降序) | 控制語法 |
| MySQL | NULL 排最前 | NULL 排最後 | ORDER BY col IS NULL, col ASC (NULL 最後) |
| PostgreSQL | NULL 排最後 | NULL 排最前 | ORDER BY col ASC NULLS LAST |
| Oracle | NULL 排最後 | NULL 排最前 | ORDER BY col ASC NULLS LAST |
| SQL Server | NULL 排最前 | NULL 排最後 | ORDER BY CASE WHEN col IS NULL THEN 1 ELSE 0 END, col |
MySQL 強制 NULL 排最後 (ASC)
ORDER BY (col IS NULL), col ASC;
-- col IS NULL 為真(1)排後,假(0)排前
實戰常見模式
| 場景 | ORDER BY 子句 | 說明 |
| 狀態優先 + 時間倒序 | status DESC, created_at DESC | 狀態 1(啟用) 在前,同狀態新資料在前 |
| 多維度權重排序 | (score1 * 0.6 + score2 * 0.4) DESC, id ASC | 加權分數主排,ID 兜底保證穩定 |
| 置頂 + 正常排序 | is_top DESC, sort_order ASC, id DESC | 置頂標記優先,其次人工排序,最後 ID 兜底 |
| 分組內排序 | category_id ASC, price DESC | 分組升序,組內價格降序 |
效能優化建議
- 組合索引順序 = ORDER BY 順序:
INDEX (status, created_at) 對應 ORDER BY status, created_at
- 方向一致性:索引預設升序,
ORDER BY a ASC, b DESC 無法完全使用索引 (MySQL 8.0 支援降序索引 INDEX (a ASC, b DESC))
- 避免 filesort:
EXPLAIN 出現 Using filesort 表示需優化索引或減少排序範圍
- LIMIT 配合:
ORDER BY ... LIMIT 10 可觸發「優先隊列排序」優化 (Priority Queue)
跨資料庫相容寫法
-- 標準 SQL (PostgreSQL, Oracle, MySQL 8.0+)
ORDER BY col1 ASC NULLS LAST, col2 DESC NULLS FIRST
-- MySQL 5.7 相容寫法
ORDER BY (col1 IS NULL), col1 ASC, col2 DESC
多欄位排序的核心是「優先級遞減」:最重要的排序鍵放最前,次重要次之,最後加上主鍵 id 保證結果確定性。記住 MySQL NULL 排序預設行為,必要時用 IS NULL 修正,索引順序務必與 ORDER BY 順序一致。
copyright ©
萬盛學電腦網 all rights reserved