Trong bài này
Thầy Nam nhận một báo cáo có đúng hai tên và một cột số xu dự kiến. Bảng nhìn gọn nhưng chưa chứng minh người viết đã chọn đúng khối hoặc tính đúng công thức. Thầy muốn kiểm tra báo cáo từ yêu cầu ban đầu đến từng dòng kết quả. Bạn sẽ chia câu truy vấn thành những bước có thể đối chiếu được.
Chuyển lời yêu cầu thành các điểm cần kiểm
Yêu cầu đầu tiên của thầy là lấy tối đa hai học viên khối 7 có nhiều xu dự kiến nhất. Xu dự kiến bằng số hiện tại cộng 10. Nếu bằng nhau, người có mã nhỏ hơn đứng trước. Kết quả chỉ cần tên và số dự kiến.
Trước khi đọc SQL, hãy chia lời yêu cầu thành các điểm cụ thể. Mỗi điểm phải có một phần câu lệnh tương ứng. Bạn có thể đánh dấu từng dòng trong bảng sau khi đã kiểm xong:
| Điểm cần kiểm | Yêu cầu cụ thể | Phần SQL tương ứng |
|---|---|---|
| Nguồn | Hồ sơ học viên | FROM students |
| Dòng | Chỉ khối 7 | WHERE grade = 7 |
| Cột | Tên, rồi xu hiện tại cộng 10 | SELECT name, coins + 10 AS after_bonus |
| Thứ tự | Dự kiến giảm, hòa thì mã tăng | ORDER BY after_bonus DESC, id ASC |
| Giới hạn | Không quá hai dòng | LIMIT 2 |
Đây là danh sách điều kiện mà kết quả phải đạt. Đúng số dòng mới chỉ đáp ứng một điều kiện. Một báo cáo có hai người khác khối vẫn sai dù có đủ cột và trình bày đẹp.
Bạn đọc truy vấn hoàn chỉnh trước để biết đích cần kiểm tra:
Dữ liệu đầu vào
students6 dòng| id | name | grade | coins |
|---|---|---|---|
| 1 | An | 6 | 120 |
| 2 | Bình | 7 | 90 |
| 3 | Chi | 8 | 180 |
| 4 | Dung | 6 | 60 |
| 5 | Huy | 9 | 180 |
| 6 | Lan | 7 | 150 |
Câu lệnh
SELECT name,
coins + 10 AS after_bonus
FROM students
WHERE grade = 7
ORDER BY after_bonus DESC, id ASC
LIMIT 2;Kết quả
| name | after_bonus |
|---|---|
| Lan | 160 |
| Bình | 100 |
Kết quả có Lan với 160 và Bình với 100. Đây là số dự kiến, trong khi cột coins của nguồn vẫn là 150 và 90. Đừng chỉ so khớp hai tên; hãy kiểm cả tiêu đề after_bonus, công thức và thứ tự hai dòng.
Danh sách này cần hai người tối đa, không đòi lúc nào cũng đủ hai người. Nếu dữ liệu sau này chỉ có một người khối 7, một dòng mới là kết quả đúng. Hãy kiểm theo điều kiện khối và số xu, thay vì nhớ tên người trong kết quả mẫu.
Theo dòng từ bảng nguồn đến cột được tính
SQL viết SELECT ở đầu, nhưng để giải thích ai được lấy, hãy bắt đầu ở nguồn. Thứ tự lôgic (logical order) là cách lần theo ý nghĩa của các bước để suy ra kết quả. Nó giúp trả lời vì sao một người được giữ hoặc bị loại.
FROMĐọc bảng nguồnWHEREGiữ dòng thỏa điều kiệnSELECTChọn và tính cộtORDER BYSắp xếp kết quảLIMITLấy tối đa số dòng
Bạn tạm bỏ công thức, thứ tự và giới hạn để kiểm bảng nguồn trước. Chỉ đọc những cột liên quan đến yêu cầu giúp tránh bỏ qua thông tin quan trọng:
Dữ liệu đầu vào
students6 dòng| id | name | grade | coins |
|---|---|---|---|
| 1 | An | 6 | 120 |
| 2 | Bình | 7 | 90 |
| 3 | Chi | 8 | 180 |
| 4 | Dung | 6 | 60 |
| 5 | Huy | 9 | 180 |
| 6 | Lan | 7 | 150 |
Câu lệnh
SELECT id, name, grade, coins
FROM students;Kết quả
| id | name | grade | coins |
|---|---|---|---|
| 1 | An | 6 | 120 |
| 2 | Bình | 7 | 90 |
| 3 | Chi | 8 | 180 |
| 4 | Dung | 6 | 60 |
| 5 | Huy | 9 | 180 |
| 6 | Lan | 7 | 150 |
Bảng có đủ thông tin để quyết định khối và tính số dự kiến. Ở bước này, bạn chưa chọn hai người đầu và chưa xếp theo xu. Nếu nguồn bị chọn nhầm sang bảng điểm, các bước sau có đúng cú pháp cũng không sửa được sai sót đó.
Tiếp theo, thêm riêng điều kiện khối để nhìn các dòng còn lại:
Dữ liệu đầu vào
studentsgiữ 2/6 dòng| id | name | grade | coins |
|---|---|---|---|
| 1 | An | 6 | 120 |
| 2 | Bình | 7 | 90 |
| 3 | Chi | 8 | 180 |
| 4 | Dung | 6 | 60 |
| 5 | Huy | 9 | 180 |
| 6 | Lan | 7 | 150 |
Câu lệnh
SELECT id, name, grade, coins
FROM students
WHERE grade = 7;Kết quả
| id | name | grade | coins |
|---|---|---|---|
| 2 | Bình | 7 | 90 |
| 6 | Lan | 7 | 150 |
Bình và Lan được giữ vì khối bằng 7. Nếu lúc này xuất hiện Chi hoặc Huy, lỗi đã nằm ở bộ lọc, chưa cần kiểm công thức. Hãy tìm bước đầu tiên khác yêu cầu, thay vì sửa mọi mệnh đề cùng lúc.
| Dòng cần thử | Câu hỏi bạn tự đặt |
|---|---|
| Một người được giữ | Người này có thật sự thuộc khối 7 không? |
| Một người bị loại | Người này bị loại vì sai điều kiện nào? |
| Người sát điều kiện | Dấu bằng có vô tình bị đổi thành lớn hơn hoặc bằng không? |
Sau khi nhóm người đúng, bạn thêm cột tính và giữ tạm cột nguồn bên cạnh. Đây là kết quả trung gian (intermediate result), tức bảng dùng để kiểm một bước trong quá trình đọc truy vấn. Nó không nhất thiết là bảng cần gửi cuối cùng.
Bạn đối chiếu số xu trước và sau phép cộng trên từng dòng:
Dữ liệu đầu vào
students6 dòng| id | name | grade | coins |
|---|---|---|---|
| 1 | An | 6 | 120 |
| 2 | Bình | 7 | 90 |
| 3 | Chi | 8 | 180 |
| 4 | Dung | 6 | 60 |
| 5 | Huy | 9 | 180 |
| 6 | Lan | 7 | 150 |
Câu lệnh
SELECT id, name, coins, coins + 10 AS after_bonus
FROM students
WHERE grade = 7;Kết quả
| id | name | coins | after_bonus |
|---|---|---|---|
| 2 | Bình | 90 | 100 |
| 6 | Lan | 150 | 160 |
Bình có cặp 90 và 100, còn Lan có cặp 150 và 160. Hai phép cộng đều đúng, nên bạn có thể chuyển sang kiểm thứ tự. Cột dự kiến không sửa coins.
Hoàn tất phần trình bày sau khi đã chọn đúng dữ liệu
Với báo cáo học viên, bạn sắp theo giá trị dự kiến rồi mới giới hạn. Bí danh after_bonus được dùng trong ORDER BY để không phải viết lại phép cộng. Mã id có thể dùng phân xử hòa dù không xuất hiện trong kết quả cuối.
Bạn kiểm lại phần cuối bằng cách giữ mã trong một bản đọc kiểm tra:
Dữ liệu đầu vào
students6 dòng| id | name | grade | coins |
|---|---|---|---|
| 1 | An | 6 | 120 |
| 2 | Bình | 7 | 90 |
| 3 | Chi | 8 | 180 |
| 4 | Dung | 6 | 60 |
| 5 | Huy | 9 | 180 |
| 6 | Lan | 7 | 150 |
Câu lệnh
SELECT id, name,
coins + 10 AS after_bonus
FROM students
WHERE grade = 7
ORDER BY after_bonus DESC, id ASC
LIMIT 2;Kết quả
| id | name | after_bonus |
|---|---|---|
| 6 | Lan | 160 |
| 2 | Bình | 100 |
Lan đứng trước Bình vì 160 lớn hơn 100. Nếu có người bằng số dự kiến, mã tăng sẽ quyết định thứ tự trong nhóm hòa. Sau khi xác nhận xong, bạn bỏ id khỏi danh sách SELECT để trả đúng hai cột mà đề yêu cầu.
Một báo cáo khác cần tối đa hai khối cao nhất có học viên đạt ít nhất 100 xu. Mỗi khối chỉ xuất hiện một lần, không cần tên từng người. Bạn phải xác định đơn vị kết quả là khối, rồi mới chọn cách loại trùng.
FROMĐọc studentsWHEREGiữ người đạt 100 xuSELECTChọn gradeDISTINCTGiữ mỗi khối một lầnORDER BYKhối lớn trướcLIMITLấy tối đa hai khối
Bạn chạy truy vấn theo đúng các bước đó:
Dữ liệu đầu vào
students6 dòng| id | name | grade | coins |
|---|---|---|---|
| 1 | An | 6 | 120 |
| 2 | Bình | 7 | 90 |
| 3 | Chi | 8 | 180 |
| 4 | Dung | 6 | 60 |
| 5 | Huy | 9 | 180 |
| 6 | Lan | 7 | 150 |
Câu lệnh
SELECT DISTINCT grade
FROM students
WHERE coins >= 100
ORDER BY grade DESC
LIMIT 2;Kết quả
| grade |
|---|
| 9 |
| 8 |
Nhóm đạt ngưỡng gồm An, Chi, Huy và Lan, thuộc các khối 6, 8, 9 và 7. Sắp khối giảm đặt 9 rồi 8 lên trước. LIMIT 2 lấy hai khối đó, không phải hai học viên đầu trong bảng nguồn.
Trong truy vấn này, bốn người qua lọc tình cờ thuộc bốn khối khác nhau. DISTINCT vẫn cần vì yêu cầu là mỗi khối một lần khi dữ liệu thay đổi. Một câu đúng với yêu cầu phải tiếp tục đúng khi có thêm người cùng khối.
| Việc kiểm | Với báo cáo học viên | Với báo cáo khối |
|---|---|---|
| Một dòng đại diện cho | Một học viên | Một khối khác nhau |
| Có loại trùng không? | Giữ từng người | Dùng DISTINCT grade |
| Giới hạn áp dụng cho | Số học viên đã sắp | Số khối đã loại trùng và sắp |
Bạn không cần thêm hàm đếm hay gom nhóm để làm hai báo cáo này. Các bài tiếp theo sẽ dạy cách tính trên nhiều dòng. Ở đây, mục tiêu là đọc rõ cách chọn dòng, tạo cột và trình bày kết quả.
Tìm lỗi bằng người bị lấy nhầm và giá trị ở ranh giới
Một truy vấn sai thường vẫn trả bảng có vẻ hợp lý. Nếu đổi điều kiện đúng bằng khối 7 thành từ khối 7 trở lên, bạn sẽ lấy thừa người. Những phần khác của câu lệnh vẫn giống báo cáo ban đầu:
Dữ liệu đầu vào
students6 dòng| id | name | grade | coins |
|---|---|---|---|
| 1 | An | 6 | 120 |
| 2 | Bình | 7 | 90 |
| 3 | Chi | 8 | 180 |
| 4 | Dung | 6 | 60 |
| 5 | Huy | 9 | 180 |
| 6 | Lan | 7 | 150 |
Câu lệnh
SELECT name,
coins + 10 AS after_bonus
FROM students
WHERE grade >= 7
ORDER BY after_bonus DESC, id ASC
LIMIT 2;Kết quả
| name | after_bonus |
|---|---|
| Chi | 190 |
| Huy | 190 |
Kết quả vẫn có hai dòng và tên cột đúng. Tuy nhiên, Chi và Huy không thuộc khối 7 nên báo cáo sai. Giới hạn che bớt các dòng, khiến việc chỉ đếm đầu ra càng khó phát hiện bộ lọc quá rộng.
Để gỡ lỗi, hãy đọc lại bảng sau WHERE trước khi lấy hai dòng. Bạn sẽ thấy cả khối 8 và 9 lọt vào. Sửa dấu so sánh trước, rồi kiểm lại công thức và thứ tự trên đúng nhóm học viên.
| Kiểu lỗi | Dữ liệu giúp phát hiện |
|---|---|
>= 7 thay cho = 7 | Một người thuộc khối 8 hoặc 9 |
> thay cho >= | Một người đúng bằng ngưỡng |
| Bỏ cột phân xử hòa | Hai người cùng số xu |
| Viết cứng tên trong lời giải | Tên thay đổi hoặc có người mới |
Với yêu cầu từ 100 đến 180 xu gồm cả hai đầu, dữ liệu mẫu có sẵn người ở cận trên nhưng chưa có cận dưới. Riêng ví dụ sau dùng bản sao đặt Bình đúng 100 xu. Các dòng khác giữ nguyên để còn giá trị dưới cận, giữa khoảng và đúng cận trên.
Bạn kiểm tra khoảng và thứ tự trên bản sao này:
Dữ liệu đầu vào
students6 dòng| id | name | coins |
|---|---|---|
| 1 | An | 120 |
| 2 | Bình | 100 |
| 3 | Chi | 180 |
| 4 | Dung | 60 |
| 5 | Huy | 180 |
| 6 | Lan | 150 |
Câu lệnh
SELECT id, name, coins
FROM students
WHERE coins BETWEEN 100 AND 180
ORDER BY coins ASC, id ASC;Kết quả
| id | name | coins |
|---|---|---|
| 2 | Bình | 100 |
| 1 | An | 120 |
| 6 | Lan | 150 |
| 3 | Chi | 180 |
| 5 | Huy | 180 |
Bình đứng đầu với 100, tiếp theo là An 120 và Lan 150. Chi cùng Huy ở cận 180 vẫn có mặt, theo thứ tự mã 3 rồi 5. Dung có 60 bị loại vì dưới cận dưới.
Trên bộ mẫu này không có ai trên 180, nên chưa kiểm được phía ngoài cận trên. Bạn nên thử thêm một dòng có hơn 180 xu khi tự kiểm lời giải. Trường hợp biên (boundary case) là dữ liệu ở sát ranh giới nơi hai cách viết dễ cho kết quả khác nhau.
- Nếu kiểm số xu, hãy thử dưới cận, đúng cận và trên cận.
- Nếu kiểm người hướng dẫn, hãy thử cả tên đã có và
NULL. Khi đề đòi cả người chưa có tên, phép<>đơn lẻ chưa đáp ứng.
Lỗi thường gặp
| Lỗi | Vì sao sai | Cách sửa |
|---|---|---|
| Chỉ kiểm hai tên cuối cùng | LIMIT có thể che bộ lọc quá rộng | Xem các dòng sau WHERE trước |
| Coi hai dòng là bằng chứng truy vấn đúng | Còn phải đúng người, cột, công thức và thứ tự | Đối chiếu từng điều kiện mà kết quả phải đạt |
| Dùng thứ tự viết làm thứ tự giải thích | SELECT đứng đầu nhưng nguồn quyết định dữ liệu cần xét | Bắt đầu từ FROM rồi theo bộ lọc |
| Chỉ thử giá trị nằm giữa khoảng | Không phát hiện việc loại nhầm hai cận | Thử dưới, đúng và trên ngưỡng |
Tóm tắt
- Hãy viết rõ nguồn, dòng, cột, thứ tự và giới hạn trước khi đánh giá một truy vấn.
- Dùng thứ tự lôgic để giải thích kết quả, không coi đó là cam kết về cách máy thực thi.
- Khi sai, tìm bước trung gian đầu tiên khác yêu cầu rồi sửa đúng phần đó.
- Bộ dữ liệu tốt có người đúng, người sai, người hòa và giá trị tại ranh giới; một bảng đẹp chưa chứng minh truy vấn đúng.
Kiểm tra nhanh
Đọc thêm
- SQLite: các bước tạo kết quả
SELECT— đối chiếu nguồn, lọc, cột kết quả và loại trùng. - SQLite: sắp xếp và giới hạn — kiểm quy tắc trình bày sau khi chọn dữ liệu.