각 테이블이 하나의 큰 퍼즐 조각이라고 생각해봐. 학생 테이블은 누가 공부하는지 알고 있고, 강좌 테이블은 무엇을 가르치는지 알려주고, 수강신청 테이블은 누가 어떤 강좌를 듣는지 보여줘. 근데 따로 보면 아무 의미 없어. 전체 그림을 보고 싶으면 이 조각들을 합쳐야 해 — 여기서 여러 개의 JOIN이 등장하는 거지.
실제로 데이터는 구조화와 중복 방지를 위해 연관된 테이블로 나눠져 있어. 예를 들어, 우리 대학 DB에는 이런 테이블들이 있어:
students— 학생 정보.enrollments— 학생의 강좌 수강신청 정보.courses— 강좌 정보.
학생, 강좌, 그리고 강사까지 전부 한 번에 보고 싶으면, 세 개의 테이블을 JOIN으로 합쳐야 해.
JOIN 실행 순서
여러 개의 JOIN을 쓸 때 PostgreSQL은 왼쪽에서 오른쪽 순서로 처리해. 즉, 먼저 앞의 두 테이블을 합치고, 그 결과를 세 번째 테이블과 합치는 식이야, 계속 반복.
예시:
SELECT *
FROM students
INNER JOIN enrollments ON students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id;
- 먼저
students와enrollments를students.id = enrollments.student_id로 합쳐. - 그 결과를
enrollments.course_id = courses.id로courses와 합쳐.
특히 테이블이 크면 실행 순서가 엄청 중요해. JOIN 구조가 잘못되면 성능이 확 떨어질 수 있어.
예시: 학생, 강좌, 강사 리스트
예를 들어, 이런 데이터 테이블이 있다고 해보자:
students 테이블:
| id | name |
|---|---|
| 1 | Otto Song |
| 2 | Maria Chi |
| 3 | Alex Lin |
courses 테이블:
| id | name | teacher |
|---|---|---|
| 101 | Mathematics | Ellen Moore |
| 102 | Physics | James Okoro |
| 103 | Computer Science | Nina Delgado |
enrollments 테이블:
| student_id | course_id |
|---|---|
| 1 | 101 |
| 1 | 103 |
| 2 | 102 |
| 3 | 101 |
쿼리:
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;
결과:
| 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 |
여러 JOIN 쿼리에서 필터링
JOIN 쿼리에도 필터 조건을 걸 수 있어. 이렇게 하면 결과 데이터가 줄고 쿼리 속도도 빨라져. 예를 들어, "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';
결과:
| student_name | course_name |
|---|---|
| Otto Song | Mathematics |
| Alex Lin | Mathematics |
여러 JOIN 쿼리 최적화
테이블이 크면 쿼리 최적화가 진짜 중요해. 몇 가지 팁을 줄게:
- 인덱스 사용하기
인덱스 덕분에 PostgreSQL이 훨씬 빠르게 동작해, 특히 키 필드로 JOIN할 때. enrollments 테이블의 student_id랑 course_id에 인덱스가 있는지 꼭 확인해.
인덱스 만드는 예시:
CREATE INDEX idx_enrollments_student_id ON enrollments(student_id);
CREATE INDEX idx_enrollments_course_id ON enrollments(course_id);
인덱스에 대해서는 다음 레벨에서 더 자세히 배울 거지만, 여기서도 언급하는 이유가 있어. JOIN이랑 엄청 자주 쓰이거든.
- 초반에 데이터 필터링하기
WHERE 조건을 써서 JOIN 전에 처리할 행 수를 줄여봐. 예시:
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';
- 합칠 행 수 최소화하기
두 테이블의 모든 행을 합치지 말고, 먼저 서브쿼리로 필터링해봐:
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;
서브쿼리(중첩 SELECT)는 바로 다음 레벨에서 더 자세히 배울 거야 :P
복잡한 JOIN 예시: 학생, 강좌, 학부
이번엔 faculties라는 테이블이 하나 더 추가됐다고 해보자:
faculties 테이블:
| id | name |
|---|---|
| 10 | Engineering |
| 20 | Natural Sciences |
courses 테이블이 이렇게 바뀜:
| id | name | teacher | faculty_id |
|---|---|---|---|
| 101 | Mathematics | Ellen Moore | 10 |
| 102 | Physics | James Okoro | 20 |
| 103 | Computer Science | Nina Delgado | 10 |
학생, 강좌, 학부까지 한 번에 보려면 JOIN을 하나 더 추가하면 돼:
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;
결과:
| student_name | course_name | faculty_name |
|---|---|---|
| Otto Song | Mathematics | Engineering |
| Otto Song | Computer Science | Engineering |
| Maria Chi | Physics | Natural Sciences |
| Alex Lin | Mathematics | Engineering |
여러 JOIN을 쓰는 SQL 쿼리는 좀 복잡할 수 있지만, 진짜 강력한 리포트와 인사이트를 뽑아낼 수 있어. 최적화랑 구조만 잘 잡으면 대용량 DB에서도 완전 유용한 무기가 될 거야.
GO TO FULL VERSION