Câu 1Câu nào sau đây mô tả đúng SELECT DISTINCT?
DISTINCT, ORDER BY, LIMIT — Định hình tập kết quả
Học SQL DISTINCT, ORDER BY, LIMIT và OFFSET. Bao gồm loại trùng lặp, sắp xếp, giới hạn hàng, và phân trang với OFFSET — tất cả chạy trực tiếp trên trình duyệt với tập dữ liệu score nạp từ CSV.
Dữ liệu sẽ dùng — bảng score nạp từ CSV
Bài này dùng bảng `score` được nạp tự động từ một file CSV để đi qua bốn cấu trúc định hình đầu ra của SELECT — DISTINCT (loại trùng lặp), ORDER BY (sắp xếp), LIMIT (số hàng), và OFFSET (bỏ qua từ đầu).
Bảng score có 5 cột — id / name / subject / score / recorded_on — với tổng cộng 15 hàng: 5 học viên (Alice / Bob / Carol / Dave / Eve) mỗi người làm 3 môn (Math / English / Science).
DISTINCT — chỉ trả về các hàng duy nhất
Một kết quả SELECT có thể chứa cùng một hàng nhiều lần. Ví dụ, lấy chỉ cột name từ score trả về 15 hàng — Alice / Bob / Carol / Dave / Eve, mỗi người ba môn.
Viết `SELECT DISTINCT col, ...` gộp các hàng trùng lặp thành một trong tập kết quả. Với nhiều cột, các hàng được coi là trùng lặp khi tổ hợp các cột khớp nhau.
-- Liệt kê các tên học viên duy nhất
SELECT DISTINCT name FROM score;
-- Liệt kê các môn học duy nhất
SELECT DISTINCT subject FROM score;
-- Loại trùng theo tổ hợp (name, subject) (= cả 15 hàng đều duy nhất)
SELECT DISTINCT name, subject FROM score;
ORDER BY — sắp xếp kết quả
SQL không đảm bảo thứ tự hàng mặc định — SELECT * FROM score; để DB tự quyết định thứ tự hàng trả về. Khi bạn muốn một thứ tự cụ thể, thêm `ORDER BY col [ASC|DESC]`.
- ASC (tăng dần / nhỏ → lớn) là mặc định và có thể bỏ
- DESC (giảm dần / lớn → nhỏ) phải được viết rõ ràng
- Một danh sách nhiều cột ngăn cách bằng dấu phẩy cho bạn sắp xếp đa cấp: các hàng bằng nhau ở cột đầu được sắp theo cột thứ hai
-- 1) Tăng dần một cột (ASC có thể bỏ)
SELECT name, score FROM score ORDER BY score;
-- 2) Giảm dần một cột
SELECT name, score FROM score ORDER BY score DESC;
-- 3) Sắp xếp nhiều cột (theo subject, rồi điểm cao nhất trước trong cùng subject)
SELECT name, subject, score FROM score ORDER BY subject ASC, score DESC;
Chi tiết về ORDER BY
- ORDER BY đặt sau `WHERE` và trước `LIMIT`. Nhớ thứ tự SELECT cols FROM table WHERE condition ORDER BY col DESC LIMIT N; thì bạn sẽ không bị nhầm.
- Vế phải của ORDER BY có thể nhận số cột (ORDER BY 2 DESC sắp theo cột thứ 2 được chọn), nhưng nó hại cho khả năng đọc — quy ước là dùng tên cột.
- Trong console của khóa học này, sắp chuỗi là chữ hoa → chữ thường (thứ tự ASCII). Một số DB coi 'A' và 'a' là tương đương.
LIMIT và OFFSET — thu hẹp số lượng và phân trang
Khi tập kết quả lớn — 100 hàng, 10.000 hàng — đổ tất cả lên màn hình thì nặng và người dùng không tiếp nhận hết được. Thêm `LIMIT N` chỉ trả về N hàng đầu. Kết hợp với `OFFSET M` để bỏ qua M hàng đầu rồi lấy N, cho bạn phân trang cho những thứ như "item 6–10" hoặc "item 11–20."
-- 1) Lấy top 5 (xếp hạng TOP 5)
SELECT name, subject, score FROM score
ORDER BY score DESC
LIMIT 5;
-- 2) Lấy item 6 đến 10 (trang 2)
SELECT name, subject, score FROM score
ORDER BY score DESC
LIMIT 5 OFFSET 5;
-- 3) Công thức phân trang: trang N, K hàng mỗi trang
-- LIMIT K OFFSET (N - 1) * K
-- ví dụ trang 3, 5 mỗi trang → LIMIT 5 OFFSET 10
| Trang | Hàng mỗi trang | OFFSET | LIMIT | Hạng đích |
|---|---|---|---|---|
| 1 | 5 | 0 | 5 | 1–5 |
| 2 | 5 | 5 | 5 | 6–10 |
| 3 | 5 | 10 | 5 | 11–15 |
| 1 | 10 | 0 | 10 | 1–10 |
| 2 | 10 | 10 | 10 | 11–20 |
| 1 | 20 | 0 | 20 | 1–20 |
LIMIT không có ORDER BY không đảm bảo thứ tự
Viết chỉ `LIMIT` và bỏ qua `ORDER BY` như SELECT * FROM score LIMIT 5; để DB tự chọn 5 hàng nào trả về. Kể cả trên DB có xu hướng trả hàng theo thứ tự insert (như SQLite), chuẩn SQL nói thứ tự không xác định. Trên MySQL / PostgreSQL, index và execution plan có thể đổi hàng nào bạn nhận.
Cho bất cứ thứ gì mà thứ tự quan trọng — xếp hạng, phân trang, "N item đầu" — luôn viết `ORDER BY` trước `LIMIT`.
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2SELECT name, score FROM score ORDER BY score DESC; trả về gì?
Câu 3SELECT * FROM score ORDER BY score DESC LIMIT 5 OFFSET 10; trả về những hàng nào?