DDevArchive
Đăng nhập

SQL: từ SELECT đến JOIN và GROUP BY

SQL là ngôn ngữ nói chuyện với database. 80% công việc chỉ quanh 4 câu: SELECT, INSERT, UPDATE, DELETE — nhưng khi dữ liệu liên quan nhau, bạn cần JOIN và GROUP BY.

SELECT cơ bản và thứ tự thực thi

// File: select.sql
-- Thứ tự LOGIC (khác thứ tự viết!):
FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT

SELECT category, count(*) AS n
FROM courses
WHERE price > 100000
GROUP BY category
HAVING count(*) >= 3
ORDER BY n DESC
LIMIT 5;

Một trong những nhầm lẫn lớn nhất: WHERE lọc trước khi gộp nhóm, còn HAVING lọc sau khi đã GROUP BY. Đặt điều kiện aggregate vào WHERE sẽ báo lỗi.

JOIN: nối hai bảng lại

Kiểu JOINKết quả
INNER JOINChỉ dòng khớp ở cả hai bảng
LEFT JOINTất cả dòng bảng trái, không khớp thì NULL
RIGHT JOINĐối xứng với LEFT (hiếm dùng)
FULL OUTER JOINTất cả dòng cả hai bảng
// File: join.sql
-- Mỗi khoá học kèm số học viên (kể cả khoá chưa ai đăng ký)
SELECT c.title, count(e.user_id) AS students
FROM courses c
LEFT JOIN enrollments e ON e.course_id = c.id
GROUP BY c.title
ORDER BY students DESC;

-- Chỉ khoá có người học
SELECT c.title
FROM courses c
JOIN enrollments e ON e.course_id = c.id;
💡 Đọc ngược để hiểu

Đọc câu query ngược từ SELECT: lấy từ đâu (FROM), ghép với ai (JOIN), lọc ra sao (WHERE/GROUP/HAVING), hiển thị gì. Cách này giúp “bắt mạch” câu SQL của người khác nhanh hơn nhiều.

Aggregate: đếm, cộng, trung bình

// File: aggregate.sql
SELECT
  count(*)        AS total,
  count(DISTINCT student_id) AS unique_students,
  round(avg(price), 0)  AS avg_price,
  sum(amount)     AS revenue,
  min(created_at) AS first_order
FROM orders;

-- count(*) đếm cả dòng NULL,
-- count(cột) chỉ đếm dòng KHÔNG NULL

Subquery và phòng tránh N+1

Subquery là câu SELECT nằm trong câu khác. Chúng rất mạnh nhưng dễ thành N+1 nếu bạn gọi trong vòng lặp ở code. Quy tắc: nếu lặp rồi query từng dòng, hãy gom lại bằng JOIN hoặc IN.

❓ Bạn muốn đếm số khoá học có giá trên mức trung bình. Bước nào bắt buộc phải dùng?

  • Thuộc thứ tự thực thi của SELECT
  • Dùng đúng INNER vs LEFT JOIN
  • Phân biệt WHERE và HAVING
  • Viết được câu có GROUP BY + count