에듀테크 프로젝트 대시보드
SQL 조인 (JOIN)
데이터베이스는 중복을 줄이려고 정보를 여러 표로 쪼개서 저장한다. 학생 정보와 동아리 정보가 따로 있을 때, "학생별 동아리 목록"을 보려면 두 표를 공통 열(키)로 이어 붙여야 한다. 그 연결 규칙이 JOIN이다.
학생 4명, 동아리 가입 기록 4건. 가입 기록의 student_id가 students.id를 가리킨다(외래 키). 눈여겨볼 점 두 가지 —
박도윤·최지우는 아직 가입 기록이 없고, 가입 기록 중 student_id = 5는 존재하지 않는 학생을 가리키는 고아 행이다.
| id | name |
|---|---|
| 1 | 김민준 |
| 2 | 이서연 |
| 3 | 박도윤 |
| 4 | 최지우 |
| student_id | club |
|---|---|
| 1 | 로봇 |
| 1 | 밴드 |
| 2 | 미술 |
| 5 | 코딩 |
조인 조건은 students.id = club_members.student_id로 고정. 버튼을 눌러 각 조인이 어떤 행을 유지하고, 어떤 칸을 NULL로 채우는지 확인해 보자.
| id | name |
|---|
| student_id | club |
|---|
| id | name | student_id | club |
|---|
| 조인 | 유지하는 행 | 짝이 없으면 | 쓰는 상황 |
|---|---|---|---|
| INNER | 양쪽 다 짝이 있는 행만 | 버린다 | "동아리에 실제로 가입한 학생만" |
| LEFT (OUTER) | 왼쪽 전부 + 짝 있으면 오른쪽 | 오른쪽을 NULL로 | "모든 학생, 없으면 동아리 빈칸" |
| RIGHT (OUTER) | 오른쪽 전부 + 짝 있으면 왼쪽 | 왼쪽을 NULL로 | "모든 가입 기록, 고아 행도 확인" |
| FULL OUTER | 양쪽 전부 | 없는 쪽을 NULL로 | "양쪽 어디에도 안 맞는 데이터 찾기" |
| CROSS | 모든 조합 (곱집합) | 조건 자체가 없음 | "모든 요일 × 모든 교시" 같은 격자 생성 |
A LEFT JOIN B 와 B RIGHT JOIN A 는 완전히 같다.
그래서 실무에서는 헷갈리지 않게 거의 LEFT JOIN만 쓰고 RIGHT는 잘 안 쓴다.
LEFT JOIN 후 WHERE 오른쪽_키 IS NULL 로 거르면, 짝이 하나도 없는 왼쪽 행만 남는다. "동아리에 아직 안 든 학생 찾기"에 자주 쓴다.
-- 어느 동아리에도 가입하지 않은 학생 SELECT s.id, s.name FROM students s LEFT JOIN club_members c ON s.id = c.student_id WHERE c.student_id IS NULL; -- 결과: 3 박도윤 / 4 최지우
COUNT(*) 로 학생 수를 세면 틀린다.ON 절에 넣어야 한다.NULL = NULL 은 참이 아니라 "알 수 없음"이라 조인 키에 NULL 이 있으면 짝이 안 잡힌다.