CodeGym /Các khóa học /SQL SELF /Nhiều JOIN trong một truy vấn

Nhiều JOIN trong một truy vấn

SQL SELF
Mức độ, Bài học
Có sẵn

Hãy tưởng tượng mỗi bảng trong database của bạn là một mảnh ghép của một bức tranh lớn. Bảng students biết ai đang học, bảng courses biết học cái gì, còn bảng enrollments biết ai đăng ký cái gì. Nhưng nếu tách riêng thì mấy mảnh này chẳng nói lên điều gì cả. Muốn nhìn thấy toàn bộ bức tranh? Phải ghép chúng lại — và đây là lúc nhiều JOIN xuất hiện.

Trong thực tế, dữ liệu thường được tổ chức thành các bảng liên kết để đảm bảo cấu trúc và tránh dư thừa. Ví dụ, trong database trường đại học của tụi mình có các bảng sau:

  • students — dữ liệu về sinh viên.
  • enrollments — thông tin về việc sinh viên đăng ký khóa học.
  • courses — thông tin về các khóa học.

Nếu muốn lấy danh sách đầy đủ sinh viên, các khóa học của họ và giáo viên, thì phải kết hợp ba bảng này bằng JOIN.

Thứ tự thực hiện JOIN

Khi dùng nhiều JOIN, PostgreSQL xử lý từ trái sang phải. Nghĩa là nó kết hợp hai bảng đầu tiên trước, sau đó kết quả đó lại kết hợp với bảng thứ ba, cứ thế tiếp tục.

Ví dụ:

SELECT *
FROM students
    INNER JOIN enrollments ON students.id = enrollments.student_id
    INNER JOIN courses ON enrollments.course_id = courses.id;
  1. Đầu tiên kết hợp bảng students và enrollments theo cột students.id = enrollments.student_id.
  2. Kết quả của lần kết hợp đầu sẽ dùng để kết hợp tiếp với bảng courses theo cột enrollments.course_id = courses.id.

Thứ tự thực hiện rất quan trọng, nhất là khi truy vấn trên bảng lớn. Cấu trúc JOIN không hợp lý có thể làm giảm hiệu năng đáng kể.

Ví dụ: Danh sách sinh viên, khóa học và giáo viên

Giả sử tụi mình có các bảng dữ liệu như sau:

Bảng students:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

Bảng courses:

id name teacher
101 Mathematics Ellen Moore
102 Physics James Okoro
103 Computer Science Nina Delgado

Bảng enrollments:

student_id course_id
1 101
1 103
2 102
3 101

Truy vấn:

SELECT
    students.name AS student_name,
    courses.name AS course_name,
    courses.teacher AS teacher_name
FROM students
    INNER JOIN enrollments ON students.id = enrollments.student_id
    INNER JOIN courses ON enrollments.course_id = courses.id;

Kết quả:

student_name course_name teacher_name
Otto Song Mathematics Ellen Moore
Otto Song Computer Science Nina Delgado
Maria Chi Physics James Okoro
Alex Lin Mathematics Ellen Moore

Lọc dữ liệu trong truy vấn với nhiều JOIN

Bạn có thể áp dụng điều kiện lọc cho truy vấn với JOIN để giới hạn dữ liệu trả về và tăng tốc độ truy vấn. Ví dụ, chỉ lấy sinh viên học môn "Mathematics":

SELECT
    students.name AS student_name,
    courses.name AS course_name
FROM students
    INNER JOIN enrollments ON students.id = enrollments.student_id
    INNER JOIN courses ON enrollments.course_id = courses.id
WHERE courses.name = 'Mathematics';

Kết quả:

student_name course_name
Otto Song Mathematics
Alex Lin Mathematics

Tối ưu hóa truy vấn với nhiều JOIN

Khi làm việc với bảng lớn, tối ưu hóa truy vấn là cực kỳ quan trọng. Đây là vài mẹo nhỏ:

  1. Dùng index

Index giúp PostgreSQL chạy nhanh hơn, nhất là khi JOIN theo các trường khóa. Hãy chắc chắn là cột student_id và course_id trong bảng enrollments có index nhé.

Ví dụ tạo index:

CREATE INDEX idx_enrollments_student_id ON enrollments(student_id);
CREATE INDEX idx_enrollments_course_id ON enrollments(course_id);

Chi tiết về index sẽ học ở level sau, nhưng mình nhắc ở đây vì nó rất hay đi kèm với JOIN.

  1. Lọc dữ liệu càng sớm càng tốt

Dùng điều kiện WHERE để giảm số dòng xử lý trước khi JOIN. Ví dụ:

SELECT
    students.name AS student_name,
    courses.name AS course_name
FROM students
    INNER JOIN enrollments ON students.id = enrollments.student_id
    INNER JOIN courses ON enrollments.course_id = courses.id
WHERE 
    courses.teacher = 'Ivan Petrov';
  1. Giảm số dòng cần JOIN

Thay vì JOIN tất cả dòng của hai bảng, hãy thử lọc trước bằng subquery:

SELECT
    students.name AS student_name,
    courses.name AS course_name
FROM 
    (SELECT * FROM students WHERE id IN (1, 2)) sub_students
INNER JOIN enrollments ON sub_students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id;

Chi tiết về SELECT lồng nhau sẽ học ở level tiếp theo :P

Ví dụ JOIN phức tạp: sinh viên, khóa học và khoa

Giả sử tụi mình có thêm bảng faculties:

Bảng faculties:

id name
10 Engineering
20 Natural Sciences

Bảng courses cập nhật:

id name teacher faculty_id
101 Mathematics Ellen Moore 10
102 Physics James Okoro 20
103 Computer Science Nina Delgado 10

Để lấy danh sách sinh viên, khóa học và khoa, tụi mình thêm một JOIN nữa:

SELECT
    students.name AS student_name,
    courses.name AS course_name,
    faculties.name AS faculty_name
FROM students
    INNER JOIN enrollments ON students.id = enrollments.student_id
    INNER JOIN courses ON enrollments.course_id = courses.id
    INNER JOIN faculties ON courses.faculty_id = faculties.id;

Kết quả:

student_name course_name faculty_name
Otto Song Mathematics Engineering
Otto Song Computer Science Engineering
Maria Chi Physics Natural Sciences
Alex Lin Mathematics Engineering

SQL với nhiều JOIN có thể hơi phức tạp, nhưng nó giúp bạn tạo ra báo cáo mạnh mẽ và lấy được thông tin giá trị. Nếu tối ưu và cấu trúc đúng, nó sẽ là công cụ xịn xò cho bạn khi làm việc với database lớn.

2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Truy vấn cơ bản với nhiều JOIN
Truy vấn cơ bản với nhiều JOIN
2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Lọc dữ liệu sử dụng WHERE và nhiều JOIN
Lọc dữ liệu sử dụng WHERE và nhiều JOIN
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION