SQL SELECT cơ bản trước khi dùng formatter | Đọc query một dòng từ log
Đừng format SQL khi bạn chưa đọc được SELECT. Formatter chỉ làm đẹp — không sửa JOIN thiếu ON, WHERE sai cột, hay SELECT * nguy hiểm. Học khung SELECT → FROM → JOIN → WHERE → ORDER BY, rồi dùng SQL formatter để indent và viết hoa từ khóa. Query từ log/Slack một dòng sẽ đọc được trong vài giây.
Junior backend, sinh viên CNTT, và freelance nhận task “sửa query chậm” thường gặp cùng một cảnh: đồng nghiệp paste một dòng SQL dài vào Telegram/Slack. Mắt chạy theo join và and nhưng không biết đoạn nào là điều kiện lọc. Bài này dạy SQL SELECT cơ bản trước formatter — đủ để bạn tự tin nhấn Format và review đúng chỗ.
Ai nên đọc bài này
- Sinh viên mới học MySQL / PostgreSQL / SQLite
- Junior lần đầu đọc query từ ORM log (Prisma, TypeORM, Sequelize)
- Freelance outsourcing nhận ticket “query trả sai số liệu” từ khách
Bạn sẽ có: khung SELECT, ví dụ trước/sau format, checklist review, case study lỗi JOIN, và cách dùng tool không cần đăng ký.
Khung SELECT bạn phải thuộc lòng
Hầu hết query đọc được nếu bạn tách thành 5 khối:
| Khối | Vai trò | Câu hỏi nhanh |
|---|---|---|
| SELECT | Cột trả về | Đang lấy cột nào? Có * không? |
| FROM | Bảng gốc | Bảng chính là gì? Alias là gì? |
| JOIN … ON | Ghép bảng | Khóa nối đúng chưa? |
| WHERE | Lọc hàng | Điều kiện nào loại bỏ dữ liệu? |
| ORDER BY / LIMIT | Thứ tự & giới hạn | Có sort/phân trang không? |
SELECT cột, cột
FROM bảng_chính AS alias
JOIN bảng_khác AS a2 ON điều_kiện_nối
WHERE điều_kiện_lọc
ORDER BY cột
LIMIT số_dòng;
Quy tắc nhớ nhanh: đọc từ FROM trước, rồi JOIN, rồi WHERE, cuối cùng mới nhìn SELECT. Nhiều người đọc SELECT trước nên bị “ngợp” vì danh sách cột dài.
SELECT * — khi nào chấp nhận
- OK: khám phá schema trên local, đếm nhanh vài dòng mẫu
- Tránh: API production, export báo cáo, query trong PR
Khi schema thêm cột lớn (JSON, text), SELECT * làm payload phình và che mất cột nào thực sự cần.
Ví dụ: query một dòng → đọc sau khi format
Giả sử bạn copy từ log NestJS / Laravel:
select u.id, u.name, o.order_date, p.product_name from users u join orders o on u.id = o.user_id join products p on o.product_id = p.id where o.status = 'completed' and o.created_at > '2024-01-01' order by o.created_at desc limit 100;
Dán vào định dạng SQL Kawa, bật Định dạng (Format) và Viết hoa từ khóa:
SELECT
u.id,
u.name,
o.order_date,
p.product_name
FROM
users u
JOIN
orders o ON u.id = o.user_id
JOIN
products p ON o.product_id = p.id
WHERE
o.status = 'completed'
AND o.created_at > '2024-01-01'
ORDER BY
o.created_at DESC
LIMIT
100;
Giờ bạn trả lời được ngay:
- Ba bảng:
users,orders,products - Chỉ đơn hoàn thành sau 2024-01-01
- 100 đơn mới nhất
Không cần đoán — cấu trúc đã hiện ra nhờ indent.
| Tình huống | Hệ quả |
|---|---|
| Một dòng, chưa format | Dễ bỏ sót điều kiện AND; review mất 10–15 phút |
| Đã format nhưng chưa biết JOIN | Nhìn đẹp nhưng vẫn không phát hiện ON sai cột |
| Biết khung + đã format | Review JOIN/WHERE trong 1–2 phút; PR sạch hơn |
JOIN và WHERE — hai chỗ hay sai nhất
1. JOIN thiếu hoặc sai khóa
-- Nguy hiểm: thiếu ON → tích Đề-các (Cartesian), số dòng nổ
SELECT u.name, o.id
FROM users u
JOIN orders o;
Sau format bạn vẫn thấy thiếu ON. Formatter không thêm điều kiện nối — bạn phải tự sửa:
SELECT u.name, o.id
FROM users u
JOIN orders o ON u.id = o.user_id;
2. Điều kiện lọc nhầm bảng
Trong outsourcing Việt Nam, hay gặp: lọc theo status nhưng quên alias — DB báo ambiguous, hoặc lọc nhầm bảng users thay vì orders.
-- Sai ngữ cảnh nghiệp vụ nếu status thuộc orders
WHERE u.status = 'completed'
-- Đúng hơn với ví dụ đơn hàng
WHERE o.status = 'completed'
3. Thứ tự đọc khi debug
- Format query
- Đếm số
JOIN - Đọc từng
ON - Đọc
WHEREtừ trên xuống - Mới nhìn danh sách cột
SELECT
Format vs Minify — dùng đúng lúc
SQL formatter có hai chế độ chính:
| Chế độ | Khi nào dùng | Ví dụ |
|---|---|---|
| Format | Đọc log, code review, giải thích cho khách | Paste từ Slack → indent |
| Minify | Nhúng vào string code / env | const q = "SELECT ..." một dòng |
| Viết hoa từ khóa | Thống nhất convention team | select → SELECT |
// Sau Minify — an toàn khi gán string một dòng
const query =
"SELECT u.id, u.name FROM users u JOIN orders o ON u.id = o.user_id WHERE o.status = 'active'";
Xử lý chạy trên trình duyệt, không cần tài khoản — phù hợp khi query có tên bảng nội bộ mà bạn không muốn upload lên dịch vụ lạ.
Cách dùng nhanh
- Mở /vi/tools/sql-formatter/
- Dán SQL (một dòng cũng được)
- Chọn Format hoặc Minify, bật viết hoa nếu team yêu cầu
- Sao chép kết quả vào PR / editor
Nếu format “lệch”, kiểm tra quote '...', ngoặc (), và cú pháp riêng (MySQL LIMIT vs SQL Server TOP).
Checklist review SQL trước khi merge
Dùng sau khi đã format:
- Không còn
SELECT *trên đường production - Mỗi
JOINcóONrõ ràng - Mọi cột trong
WHERE/ORDER BYcó alias khi nhiều bảng - Có
LIMIThoặc phân trang nếu query có thể trả hàng nghìn dòng - Điều kiện ngày/giờ ghi rõ timezone hoặc convention team
- Đã chạy
EXPLAIN(hoặc tương đương) với dữ liệu gần production nếu query nặng
Case study: freelance sửa báo cáo sai số
Khách gửi: “Doanh thu tháng 6 sai.” Query gốc một dòng, có LEFT JOIN payments nhưng WHERE payment.status = 'paid' — vô tình biến thành inner filter, loại đơn chưa thanh toán khỏi báo cáo “tất cả đơn.”
Sau khi format, junior thấy WHERE gắn vào cột của bảng join trái. Đổi điều kiện vào ON hoặc tách báo cáo “đã thanh toán” vs “tất cả đơn.” Format không sửa bug — nhưng giúp nhìn ra bug trong 2 phút thay vì nửa buổi.
Lỗi thường gặp khi mới học SELECT
| Lỗi | Triệu chứng | Cách xử lý |
|---|---|---|
| Quên alias | column ambiguously defined | Thêm u. / o. |
| Quote lệch | Format hỏng / syntax error | Đếm cặp ' |
Nhầm WHERE và HAVING | Lọc aggregate sai | WHERE trước group; HAVING sau |
Copy SQL từ ORM có ? | Không chạy trực tiếp | Thay param bằng giá trị mẫu (che PII) |
FAQ thực tế
Có cần cài app để format SQL không?
Không. Dùng SQL formatter trên trình duyệt là đủ cho review và minify nhanh.
PostgreSQL và MySQL format khác nhau không?
Khung SELECT giống nhau. Khác ở hàm (ILIKE, LIMIT/OFFSET) và một số kiểu. Formatter chuẩn SQL vẫn giúp đọc cấu trúc; dialect-specific cần mắt người.
ORM đã generate SQL rồi, còn cần biết SELECT?
Có. Khi production chậm, bạn vẫn đọc raw SQL trong log. Không hiểu SELECT thì không tối ưu được index hay JOIN.
Liên kết liên quan
- Công cụ SQL formatter — format, minify, viết hoa từ khóa
- Danh sách công cụ
- JSON formatter — khi debug payload API kèm query