Sắp xếp giảm dần
Bạn sẽ học được
- Đảo chiều sắp xếp bằng
DESCvà kết hợp nhiều chiều trong một câu. - Dùng
DESCcho số, ngày và chuỗi với kết quả khác nhau. - Kiểm soát vị trí của
NULLbằngNULLS FIRST/NULLS LAST. - Viết mẫu truy vấn "top N" đúng thứ tự.
- Nhận ra lỗi khi sắp xếp hỗn hợp mà không kiểm tra từng cột.
Khái niệm cốt lõi
ASC là mặc định. DESC đảo chiều: số lớn trước, ngày mới trước, chuỗi theo thứ tự đảo của collation. Cú pháp đặt ngay sau cột:
SELECT name, price
FROM products
ORDER BY price DESC;Mỗi cột có thể có chiều riêng:
SELECT category, name, price
FROM products
ORDER BY category ASC, price DESC;Đọc là: nhóm theo category tăng dần; trong mỗi nhóm, giá giảm dần. Đây là mẫu "nhóm chính — chi tiết phụ" rất phổ biến. Điều quan trọng là chiều được gắn vào từng cột, không phải vào cả câu. Viết ORDER BY category, price DESC cho kết quả giống hệt vì ASC là mặc định.
Với số, DESC cho danh sách từ lớn đến nhỏ — nền tảng của mọi báo cáo "top". Với ngày, DESC cho bản ghi mới nhất trước, phù hợp với bảng tin hoặc lịch sử giao dịch. Với chuỗi, DESC đảo thứ tự alphabet; ít dùng hơn nhưng hữu ích khi cần "Z đến A".
NULL có quy tắc mặc định đáng nhớ trong PostgreSQL:
| Chiều | Vị trí mặc định của NULL |
|---|---|
ASC | Cuối cùng (NULLS LAST) |
DESC | Đầu tiên (NULLS FIRST) |
Lý do: PostgreSQL coi NULL là lớn hơn mọi giá trị khác. Khi sắp tăng dần, nó nằm cuối; khi sắp giảm dần, nó nằm đầu. Nếu không muốn vậy, ghi rõ:
ORDER BY email DESC NULLS LASTĐiều này quan trọng trong báo cáo: một danh sách "khách mới nhất" sắp theo ngày đăng ký mà cột ngày cho phép NULL sẽ bắt đầu bằng các dòng thiếu ngày, không phải người mới nhất. Luôn kiểm tra dữ liệu thiếu trước khi cam kết thứ tự.
Một lưu ý về chuỗi: DESC không có nghĩa "từ A đến Z đảo ngược đẹp mắt" khi có dấu tiếng Việt. Collation quyết định, và đảo chiều chỉ đảo kết quả của collation đó. Với dữ liệu có nhiều ngôn ngữ, hãy thử trên dữ liệu thật trước khi dùng trong báo cáo.
Cuối cùng, mẫu top-N:
SELECT name, price
FROM products
ORDER BY price DESC
LIMIT 5;Thứ tự thực thi là sắp xếp trước, cắt sau. Nếu đảo lại — LIMIT trước ORDER BY — câu lệnh sai cú pháp. Nếu bỏ ORDER BY, LIMIT 5 lấy năm dòng bất kỳ, không phải năm dòng đắt nhất. Đây là lỗi logic phổ biến nhất khi viết top-N.
Ví dụ chạy được
Sản phẩm từ đắt đến rẻ:
SELECT name, price
FROM products
ORDER BY price DESC;| name | price |
|---|---|
| Nồi chiên không dầu | 1690000 |
| Bàn phím cơ | 1250000 |
| Tai nghe Bluetooth | 890000 |
| Chuột không dây | 450000 |
| Giá kê laptop | 390000 |
| Bình giữ nhiệt | 320000 |
| Đèn bàn LED | 290000 |
| Áo thun cotton | 250000 |
| Sách SQL thực chiến | 180000 |
Chín dòng, đúng là đảo của danh sách tăng dần ở bài trước. Kiểm tra chéo này rất hữu ích: nếu hai danh sách không phải đảo của nhau, có thể bạn đã sắp sai cột hoặc dữ liệu thay đổi giữa hai lần chạy.
Khách mới đăng ký trước:
SELECT name, signup_date
FROM customers
ORDER BY signup_date DESC;Mười hai dòng, bắt đầu Nga Lý (30/06/2025), Minh Dương (21/04/2025), Linh Ngô (09/03/2025), Khánh Hồ (14/02/2025), Inh Đỗ (10/01/2025), rồi Hà Bùi (02/11/2024), Giang Đặng (18/08/2024), Em Võ (05/05/2024), Dũng Phạm (20/02/2024), Chi Lê (15/01/2024), Bình Trần (01/07/2023), An Nguyễn (12/03/2023).
Sắp hai chiều trong một nhóm:
SELECT name, category, price
FROM products
WHERE category = 'Điện tử'
ORDER BY price DESC;Ba dòng: Bàn phím cơ (1250000), Tai nghe Bluetooth (890000), Chuột không dây (450000). Lọc trước rồi sắp là cách đơn giản nhất để kiểm tra một nhóm mà không phụ thuộc thứ tự giữa các nhóm.
Sắp theo nhóm và giá:
SELECT category, name, price
FROM products
ORDER BY category, price DESC;Kết quả gồm bốn nhóm. Trong nhóm Điện tử: Bàn phím, Tai nghe, Chuột. Trong nhóm Gia dụng: Nồi chiên, Giá kê, Bình giữ nhiệt, Đèn bàn. Nhóm Sách có một dòng, Thời trang có một dòng. Thứ tự giữa các nhóm phụ thuộc collation nên có thể khác giữa các môi trường; đừng viết báo cáo dựa vào thứ tự đó nếu chưa kiểm tra.
Minh họa NULL:
SELECT name, email
FROM customers
ORDER BY email DESC;Hai dòng đầu là Dũng Phạm và Inh Đỗ — cả hai có email là NULL, và DESC đặt NULL lên trước. Nếu muốn họ ở cuối:
SELECT name, email
FROM customers
ORDER BY email DESC NULLS LAST;Khi đó danh sách bắt đầu bằng nga@example.com và kết thúc bằng hai dòng NULL. Sự khác biệt này là lý do các báo cáo "mới nhất" cần chỉ định NULLS LAST nếu cột có thể thiếu.
Thực hành
- Viết truy vấn lấy ba sản phẩm đắt nhất. Kết quả phải là Nồi chiên, Bàn phím, Tai nghe. Sau đó đổi
LIMIT 3thànhLIMIT 2và dự đoán trước khi chạy. - Sắp đơn theo
order_date DESCvà đếm năm đơn mới nhất. Đối chiếu với danh sách ngày trong bảng để chắc mình không bỏ sót. - Viết truy vấn sắp khách theo
segment DESC, name ASC. Giải thích vì sao thứ tự nhómsegmentcó thể khác dự đoán. - Chạy truy vấn email
DESCcó và không cóNULLS LAST. Đếm vị trí của hai dòngNULLđể xác nhận quy tắc mặc định.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
| Kết quả vẫn tăng dần | Quên DESC | Thêm DESC sau đúng cột |
| Chỉ cột đầu tiên bị đảo | DESC đặt sau cột cuối nhưng không cho cột đầu | Gắn DESC riêng cho từng cột |
Dòng NULL nằm đầu danh sách | Mặc định của DESC | Thêm NULLS LAST |
LIMIT lấy dòng bất kỳ | Thiếu ORDER BY | Sắp xếp trước khi giới hạn |
| Hai lần chạy ra thứ tự khác nhau | Các dòng bằng nhau ở cột sắp xếp | Thêm cột duy nhất làm tie-breaker |
Lỗi "chỉ cột đầu tiên bị đảo" xảy ra khi viết ORDER BY category DESC, price và tưởng rằng DESC áp dụng cho cả hai. Thực tế price vẫn tăng dần. Muốn cả hai giảm, viết ORDER BY category DESC, price DESC.
Tóm tắt
DESCđảo chiều từng cột;ASClà mặc định.- Trong PostgreSQL,
DESCđặtNULLlên đầu; dùngNULLS LASTnếu không muốn. - Top-N luôn là
ORDER BY ... LIMIT n, không có ngoại lệ. - Kiểm tra chéo danh sách tăng dần và giảm dần để phát hiện lỗi.
- Thứ tự nhóm chuỗi phụ thuộc collation; đừng giả định.
Use ← → to move between lessons