Join Type
- INNER
- OUTER
Join condition
- NATURAL
- ON
- USING
간단한 표
| 설명 | 주의할 점! | |
| INNER JOIN | 매칭되는 튜플만 남김 | 양쪽에 매칭이 없는 데이터는 버림 |
| OUTER JOIN | 매칭 안 되는 데이터도 살림 (NULL로 채움) | LEFT, RIGHT, FULL로 구분 |
| NATURAL JOIN | 공통 컬럼을 자동 매칭 | 의도치 않게 잘못 매칭될 수 있음!! 조심! |
| ON | 매칭할 조건을 명시 | 직접 어떤 칼럼을 매칭할지 써야 함 |
| USING | 공통 컬럼만 지정해서 매칭 | 지정한 컬럼만 비교함 |
1. Natural join
: join하고자 하는 두 테이블의 이름이 같은 속성(공통 속성)에 대해 알아서(자동으로) 매칭 해줌
-> 중복제거해서 공통 속성은 하나만 남김
*inner join은 다 남김
FROM a NATURAL JOIN b NATURAL JOIN c
=> 이런식으로 여러개 join 가능
조건: 같은 이름의 column을 공유해야함
그런데 "공통 컬럼 기준이 명확하지 않으면, 엉뚱한 매칭이 일어날 수도 있다."

무슨 말이냐면,,,,


SELECT dept_name, course_id, name, title, credits
FROM student NATURAL JOIN takes NATURAL JOIN course;
student, takes, course 테이블에 공통 이름을 가진 컬럼이 여러 개 존재
- dept_name: student, course
- ID: students, takes
- course_id: takes, courese
but, NATURAL JOIN은 이름만 보고 무조건 자동으로 매칭을 걸기 때문에,
아래와 같은 순서로 join이 이뤄짐
- student 와 takes 사이:
- ID가 같으면 조인됨 →
→ 학생과 그 학생의 수강 내역 연결
- ID가 같으면 조인됨 →
- takes 와 course 사이:
- course_id가 같으면 조인됨 →
→ 학생이 수강한 과목의 정보(과목명 등) 연결
- course_id가 같으면 조인됨 →
- student 와 course 사이:
- dept_name이 겹치는 바람에,
- 추가로 dept_name까지 자동으로 매칭돼버림.
- 그래서 학생 전공 == 과목 소속 학과인 경우만 남게 됨.
원래 의도는:
- 학생이 수강한 모든 과목 정보를 보여주려 했던 것.
- 그런데, 학생의 전공 학과 과목만 남아서, 다른 학과 과목 수강한 내역이 다 누락됨.
이러한 문제를 해결하기 위해서는! 카티션 프로덕트를 이용해 조건을 걸면 됨.
SELECT name, title
FROM student NATURAL JOIN takes, course
WHERE takes.course_id = course.course_id;
만약...
테이블에 공통 속성이 여러개라면 => 세개 다 값이 일치할 경우 return! = 매칭 조건이 강해진다
ex)
| student 테이블 | takes 테이블 |
| ID | ID |
| dept_name | dept_name |
| year | year |
| name | course_id |
NATURAL JOIN은 이 세 컬럼 모두를 동시에 비교 -> ID도 같고, dept_name도 같고, year도 같은 레코드끼리만 매칭
2. INNER JOIN: 교집합
: 사용할 컬럼 명을 지정해서 매칭함
USING
: 매칭 할 column명을 명시
SELECT name, title
FROM (student NATURAL JOIN takes)
JOIN course USING (course_id);
USING (column 명)
여기에 쓰이는 column 명은 두 테이블에 모두 존재해야함
ON
: join의 조건
SELECT student.name, course.title
FROM student
JOIN takes ON student.ID = takes.ID
JOIN course ON takes.course_id = course.course_id;
=> 어떠한 column으로 join을 진행하는지 알 수 있음
think....
안전하긴한데,,, 교집합만 return하기 때문에, loss가 꽤 많다!
교집합 외에도 보고싶은데..???!!!
3. OUTER JOIN
: 조인을 할 때 매칭이 안 되어도, 테이블의 데이터를 살려서 보여줌
- LEFT OUTER JOIN
- RIGHT OUTER JOIN
- FULL OUTER JOIN
a. LEFT OUTER JOIN
SELECT *
FROM student
LEFT JOIN takes
ON student.ID = takes.ID;
- student 테이블은 모두 결과에 나옴.
- takes에 매칭되는 게 없으면, takes 쪽은 NULL로 채움.
✅ 왼쪽(student) 보존, 오른쪽(takes)은 NULL 될 수 있음.
b. RIGHT OUTER JOIN
SELECT *
FROM student
RIGHT JOIN takes
ON student.ID = takes.ID;
- takes 테이블은 모두 결과에 나옴.
- student에 매칭되는 게 없으면, student 쪽은 NULL로 채움.
✅ 오른쪽(takes) 보존, 왼쪽(student)은 NULL 될 수 있음.
c. FULL OUTER JOIN
SELECT *
FROM student
FULL JOIN takes
ON student.ID = takes.ID;
- student에도 없고, takes에도 없는 매칭 실패 데이터까지
모두 결과에 나온다 (각각 NULL로 채워진다).
✅ 왼쪽 + 오른쪽 모두 보존!
=> MySQL에는 FULL OUTER JOIN이 없다!
LEFT + UNION + RIGHT로 대체
SELECT ...
FROM A
LEFT JOIN B ON A.id = B.id
UNION
SELECT ...
FROM A
RIGHT JOIN B ON A.id = B.id;

GPT가 만든 내용 확인 문제
문제 1. 기본 INNER JOIN
Q1.
학생(student) 테이블과 수강(takes) 테이블이 있다.
학생 이름(name)과 수강한 과목(course_id)를 출력하는 쿼리를 작성하라.
SELECT name, course_id
FROM students JOIN takes ON students.ID = takes.ID;
Q2.
모든 학생 이름(name)과 그들이 수강한 과목(course_id)을 출력하되,
수강하지 않은 학생도 결과에 나오도록 해라.
(= student 기준으로 모두 출력, 수강 안 한 학생은 course_id가 NULL이어야 함)
SELECT name, course_id
FROM student
LEFT JOIN takes ON student.ID = takes.ID;
Q3.
student와 takes를 NATURAL JOIN할 때 주의해야 할 점을 쓰시오.
(서술형, 방금 공부한 거 응용)
공통 속성이 여러개일 경우 의도하지 않은 결과가 나올 수 있으므로 매칭하고 싶은 column을 명시한다.
Q4.
course 테이블과 prereq 테이블이 있다.
모든 과목(course)과 그 과목의 선수과목(prereq)을 연결해서 출력하고,
선수과목이 없는 과목과 등록 안 된 선수과목도 모두 결과에 나오게 하라.
(힌트: FULL JOIN 필요! MySQL이면 대체 방법 생각!)
SELECT *
FROM course LEFT JOIN prereq ON course.course_id = prereq.course_id
UNION
SELECT *
FROM course RIGHT JOIN prereq ON course.course_id = prereq.course_id;
'공부 > 데이터베이스' 카테고리의 다른 글
| Relational Data (0) | 2025.04.29 |
|---|---|
| SQL data manipulation language(DML) (0) | 2025.04.03 |