Hãy tưởng tượng bạn đang làm việc với một cơ sở dữ liệu khổng lồ về sinh viên. Sắp xếp họ chỉ theo họ thôi thì cũng hữu ích rồi, nhưng thử nghĩ xem nếu trong bảng của bạn có nhiều sinh viên trùng họ thì sao. Lúc này, để kết quả dễ đọc hơn, bạn có thể thêm sắp xếp theo tên nữa. Hoặc ví dụ khác: bạn muốn sắp xếp danh sách đơn hàng trước tiên theo ngày, sau đó theo tổng số tiền đơn hàng. Và đây là lúc sắp xếp theo nhiều cột phát huy tác dụng.
Sắp xếp theo nhiều cột cho phép bạn: 1. Sắp xếp dữ liệu theo thứ tự xác định rõ ràng; 2. Kiểm soát ưu tiên sắp xếp (trước theo một cột, sau đó theo cột khác); 3. Hiển thị dữ liệu có cấu trúc và dễ đọc hơn.
Cú pháp sắp xếp theo nhiều cột
Để sắp xếp dữ liệu theo nhiều cột, bạn dùng toán tử quen thuộc ORDER BY, nhưng giờ bạn liệt kê nhiều cột cách nhau bằng dấu phẩy. PostgreSQL sẽ sắp xếp trước theo cột đầu tiên, nếu giá trị giống nhau thì mới xét tiếp cột thứ hai, cứ thế tiếp tục.
Đây là cú pháp tổng quát:
SELECT cột
FROM bảng
ORDER BY cột1 hướng1, cột2 hướng2, ... ;
Trong đó:
cột1,cột2, ... — là các cột bạn muốn sắp xếp theo.hướng1,hướng2, ... — là hướng sắp xếp (ASC— tăng dần,DESC— giảm dần).- Tham số này không bắt buộc, mặc định là
ASC.
Ví dụ 1: Sắp xếp sinh viên theo họ, rồi theo tên
Giả sử có bảng students với dữ liệu về sinh viên:
| 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 |
Nhiệm vụ của chúng ta là sắp xếp sinh viên trước theo họ (last_name), sau đó theo tên (first_name).
SELECT id, first_name, last_name, age
FROM students
ORDER BY last_name ASC, first_name ASC;
Kết quả:
| 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 |
Như bạn thấy, các dòng được sắp xếp trước theo họ (Kim, rồi Lin), sau đó theo tên (Anna, Maria, v.v.). Cách này cực kỳ hữu ích khi bạn cần tìm nhanh một người trong danh sách hoặc sắp xếp sổ điểm.
Ví dụ 2: Sắp xếp đơn hàng theo ngày và tổng tiền
Giả sử có bảng orders với dữ liệu về đơn hàng:
| 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 |
Chúng ta muốn sắp xếp đơn hàng trước theo ngày order_date, sau đó theo tổng tiền total giảm dần.
SQL query:
SELECT order_id, customer_id, order_date, total
FROM orders
ORDER BY order_date ASC, total DESC;
Kết quả:
| 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 |
Như bạn thấy, các đơn hàng có cùng ngày cũng được sắp xếp theo tổng tiền.
Làm việc với NULL khi sắp xếp: NULLS FIRST và NULLS LAST
Trong SQL có giá trị đặc biệt - NULL, nghĩa là không có giá trị. Chi tiết về cách làm việc với nó mình sẽ nói ở các level sau. Nhưng bây giờ là lúc hợp lý để chỉ cho bạn cách kiểm soát vị trí của nó khi sắp xếp.
Khi bạn sắp xếp các cột có chứa NULL, PostgreSQL phải quyết định đặt giá trị rỗng ở đâu: đầu hay cuối.
Mặc định:
- Với
ORDER BY ... ASC:NULLsẽ ở cuối (NULLS LAST) - Với
ORDER BY ... DESC:NULLsẽ ở đầu (NULLS FIRST)
Đôi khi hành vi này không tiện — và bạn có thể kiểm soát rõ ràng bằng NULLS FIRST hoặc NULLS LAST.
Cú pháp:
ORDER BY cột ASC NULLS FIRST
ORDER BY cột DESC NULLS LAST
Ví dụ: sắp xếp theo điểm, trong đó NULL — "chưa có điểm"
SELECT student_id, grade
FROM grades
ORDER BY grade DESC NULLS LAST;
Như vậy, bạn sẽ thấy trước tiên là các sinh viên điểm cao nhất, rồi thấp dần, và ở cuối cùng — những ai chưa có điểm (NULL).
Ví dụ: ngược lại — hiển thị sinh viên chưa có điểm lên đầu
Giả sử có bảng grades, trong đó một số sinh viên chưa có điểm (NULL):
| student_id | grade |
|---|---|
| 101 | NULL |
| 102 | 85 |
| 103 | NULL |
| 104 | 92 |
| 105 | 76 |
Chúng ta muốn hiển thị trước sinh viên chưa có điểm, sau đó là các bạn còn lại theo thứ tự tăng dần điểm.
SELECT student_id, grade
FROM grades
ORDER BY grade ASC NULLS FIRST;
Kết quả:
| student_id | grade |
|---|---|
| 101 | NULL |
| 103 | NULL |
| 105 | 76 |
| 102 | 85 |
| 104 | 92 |
Toán tử NULLS FIRST kết hợp với ORDER BY grade ASC đảm bảo các dòng có NULL sẽ ở đầu, sau đó là các điểm tăng dần.
Một số lưu ý và lỗi thường gặp
Người mới hay quên chỉ rõ hướng sắp xếp cho từng cột. Nếu bạn không ghi hướng, PostgreSQL mặc định dùng ASC. Ngoài ra, cũng dễ quên rằng thứ tự các cột trong ORDER BY rất quan trọng: trước tiên dữ liệu được sắp xếp theo cột đầu, nếu giá trị cột đầu giống nhau thì mới xét tiếp cột sau.
GO TO FULL VERSION