SQL SELECT cơ bản trước khi dùng formatter | Đọc query một dòng từ log

(Cập nhật: 19 tháng 7, 2026 ) SQL SELECT SQL formatter JOIN MySQL PostgreSQL code review
Kết luận

Đừ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 joinand 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ốiVai tròCâu hỏi nhanh
SELECTCột trả vềĐang lấy cột nào? Có * không?
FROMBảng gốcBảng chính là gì? Alias là gì?
JOIN … ONGhép bảngKhóa nối đúng chưa?
WHERELọc hàngĐiều kiện nào loại bỏ dữ liệu?
ORDER BY / LIMITThứ tự & giới hạnCó 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)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:

  1. Ba bảng: users, orders, products
  2. Chỉ đơn hoàn thành sau 2024-01-01
  3. 100 đơn mới nhất

Không cần đoán — cấu trúc đã hiện ra nhờ indent.

Trước và sau khi hiểu khung SELECT
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

  1. Format query
  2. Đếm số JOIN
  3. Đọc từng ON
  4. Đọc WHERE từ trên xuống
  5. 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ùngVí dụ
FormatĐọc log, code review, giải thích cho kháchPaste từ Slack → indent
MinifyNhúng vào string code / envconst q = "SELECT ..." một dòng
Viết hoa từ khóaThống nhất convention teamselectSELECT
// 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

  1. Mở /vi/tools/sql-formatter/
  2. Dán SQL (một dòng cũng được)
  3. Chọn Format hoặc Minify, bật viết hoa nếu team yêu cầu
  4. 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 JOINON rõ ràng
  • Mọi cột trong WHERE / ORDER BY có alias khi nhiều bảng
  • LIMIT hoặ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ỗiTriệu chứngCách xử lý
Quên aliascolumn ambiguously definedThêm u. / o.
Quote lệchFormat hỏng / syntax errorĐếm cặp '
Nhầm WHEREHAVINGLọc aggregate saiWHERE trước group; HAVING sau
Copy SQL từ ORM có ?Không chạy trực tiếpThay 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