想象一下,你在搞一个超大的学生数据库。只按姓排序已经挺有用了,但你想想,如果表里有好几个学生同姓,那你看起来就有点乱。这时候,为了让结果更清晰,你可以再加个名字排序。再比如,你想先按订单日期排,再按订单总额排。这种时候,多列排序就派上用场了。
多列排序能让你:1. 按你想要的顺序整理数据;2. 控制排序优先级(先按一列,再按另一列);3. 让数据输出更有结构、更容易看懂。
多列排序的语法
要按多列排序,用的还是熟悉的ORDER BY,不过这次你要用逗号把多个列名分开。PostgreSQL会先按第一个列排,如果有一样的,再按第二个,以此类推。
通用语法如下:
SELECT 列们
FROM 表
ORDER BY 列1 排序1, 列2 排序2, ... ;
这里:
列1、列2、... —— 就是你想排序的那些列。排序1、排序2、... —— 排序方向(ASC升序,DESC降序)。- 这个参数可选,默认是
ASC。
例子1:先按姓再按名排序学生
假设有个students表,里面是学生信息:
| id | first_name | last_name | age |
|---|---|---|---|
| 1 | Anna | Lin | 20 |
| 2 | Victor | Lin | 22 |
| 3 | Maria | Kim | 21 |
| 4 | Otto | Lin | 23 |
| 5 | Anna | Kim | 20 |
我们的目标——先按姓(last_name),再按名(first_name)排序学生。
SELECT id, first_name, last_name, age
FROM students
ORDER BY last_name ASC, first_name ASC;
结果:
| id | first_name | last_name | age |
|---|---|---|---|
| 5 | Anna | Kim | 20 |
| 3 | Maria | Kim | 21 |
| 1 | Anna | Lin | 20 |
| 4 | Otto | Lin | 23 |
| 2 | Victor | Lin | 22 |
可以看到,先按姓(Kim,然后Lin)排,再按名(Anna、Maria等)。这种方式特别适合你要快速找人,或者要把名单排好序的时候。
例子2:按订单日期和金额排序
假设有个orders表,里面是订单信息:
| order_id | customer_id | order_date | total |
|---|---|---|---|
| 1 | 101 | 2025-10-01 | 500 |
| 2 | 102 | 2025-10-03 | 200 |
| 3 | 103 | 2025-10-02 | 300 |
| 4 | 104 | 2025-10-01 | 100 |
| 5 | 101 | 2025-10-03 | 600 |
我们想先按order_date排,再按total降序排。
SQL查询:
SELECT order_id, customer_id, order_date, total
FROM orders
ORDER BY order_date ASC, total DESC;
结果:
| order_id | customer_id | order_date | total |
|---|---|---|---|
| 1 | 101 | 2025-10-01 | 500 |
| 4 | 104 | 2025-10-01 | 100 |
| 3 | 103 | 2025-10-02 | 300 |
| 5 | 101 | 2025-10-03 | 600 |
| 2 | 102 | 2025-10-03 | 200 |
可以看到,同一天的订单会再按金额排。
排序时处理NULL:NULLS FIRST和NULLS LAST
SQL里有个特殊值——NULL,意思是“没值”。具体怎么用以后再说,不过现在正好可以看看排序时怎么控制它。
当你排序的列里有NULL,PostgreSQL得决定这些空值放哪:开头还是结尾。
默认情况下:
- 用
ORDER BY ... ASC时:NULL会排在最后(NULLS LAST) - 用
ORDER BY ... DESC时:NULL会排在最前面(NULLS FIRST)
有时候你不喜欢默认的,你可以用NULLS FIRST或NULLS LAST手动指定。
语法:
ORDER BY 列 ASC NULLS FIRST
ORDER BY 列 DESC NULLS LAST
例子:按成绩排序,NULL表示“还没打分”
SELECT student_id, grade
FROM grades
ORDER BY grade DESC NULLS LAST;
这样你会先看到分高的,再看到分低的,最后才是还没打分(NULL)的。
反过来——先显示没分的学生
假设有个grades表,有些学生还没分数(NULL):
| student_id | grade |
|---|---|
| 101 | NULL |
| 102 | 85 |
| 103 | NULL |
| 104 | 92 |
| 105 | 76 |
我们想先把没分的学生排前面,后面再按分数升序排其他学生。
SELECT student_id, grade
FROM grades
ORDER BY grade ASC NULLS FIRST;
结果:
| student_id | grade |
|---|---|
| 101 | NULL |
| 103 | NULL |
| 105 | 76 |
| 102 | 85 |
| 104 | 92 |
NULLS FIRST配合ORDER BY grade ASC,就能保证NULL的记录在最前面,后面才是分数升序。
注意事项和常见错误
新手经常忘了给每个列写排序方向。如果你没写,PostgreSQL默认用ASC。还有一个常见坑,就是忘了ORDER BY里列的顺序很重要:先按第一个列排,只有第一个列一样时才按第二个列排。
GO TO FULL VERSION