Join 연산
릴레이션들의 공통 속성을 중심으로 두 개의 릴레이션을 함쳐 새로운 릴레이션을 생성
왜 Join이 필요한가? → 카테션 곱은 전체의 조합을 만들기 때문에 성능이 떨어짐
DB에서의 의미: 여러 테이블을 거쳐서 값 가져오기
Join끼리 비교
Inner Join
Inner Join은 테이블 간의 공통 요소 (교집합)를 중심으로 새로운 릴레이션으로 생성하는 조인입니다.
Theta Join
조건을 지정한 조인입니다.
r ⋈θ s 로 표현합니다.
SELECT *
FROM table1
JOIN table2 ON table1.columnA < table2.columnB
Equi Join
Theta join
에서 조건이 =
인 연산을 의미힙니다.
Join의 결과가 특정 조건값과 일치하는 결과를 릴레이션으로 생성하는 조인
-
조건을 적지 않은 경우, 카테션 곱처럼 전체의 조합을 만듦
-
따라서 Join시 조건을 명시해야 함
-
STUDENT
테이블과DEPARTMENT
테이블을 사용하여
학생이름(sname), 전공 학과번호(deptno), 전공 학과 이름(dname) 가져오기
-
Oracle 방식
SELECT s.sname "학생이름", s.deptno "학과번호", d.dname "학과이름" FROM STUDENT s, DEPARTMENT d WHERE s.deptno = d.deptno;
-
ANSI 방식 (SQL 표준)
SELECT s.sname "학생이름", s.deptno "학과번호", d.dname "학과이름" FROM STUDENT s JOIN DEPARTMENT d ON s.deptno = d.deptno;
Non Equi Join
Join의 결과가 특정 범위내에 존재하는 결과를 릴레이션으로 생성하는 조인
직원(직원 ID, 이름, 급여)
근무(직원 ID, 팀 ID, 근무 시간)
팀(팀 ID, 팀 이름, 예산, 관리자 직원 ID)
-
근무 시간이 50 이상 100이하인 직원의 이름, 나이, 급여를 출력
SELECT e.ename, e.age, e.sal FROM EMP e JOIN WORK w ON e.id=w.eid WHERE w.time_hour BETWEEN 50 AND 100
-
직원의 급여 범위내에 해당하는 등급 출력
SALGRADE(급여 등급 ID, 최소 급여, 최대 급여, 급여 등급 이름)
SELECT e.sal 급여, s.name "급여 등급" FROM EMP e JOIN SALGRADE s ON e.sal BETWEEN s.losal AND s.hisal;
-
결과
급여 급여 등급 10001 S+ 1000 C 100 C 2100 A
-
Natural Join
Equi 조인에서 중복되는 공통 컬럼을 최소화하는 조인
- 두 테이블 간의 공통 컬럼에 대해 Inner Join은 별개의 컬럼으로 나타내지만 Natural Join은 하나의 컬럼으로 표현
SELECT ename, deptno, dname
FROM EMP NATURAL JOIN DEPT;
이 경우, 공통 컬럼인 deptno
를 이용해서 Equi 조인과는 다르게 명시하지 않고도 암묵적으로 짧게 조인할 수 있습니다.
대신 주의할 점은 컬럼의 이름으로 연결하기 때문에 id
나 name
같이 흔한 컬럼 이름인 경우, 잘못 조인할 수도 있습니다.
Outer Join
이전의 Inner Join은 양측 컬럼 값 중 하나라도 NULL인 경우, =
(equal) 결과가 거짓이 되어 NULL 값이 생략됩니다.
Outer Join은 조건에 해당하는 컬럼이 NULL이라서 생략되는 정보를 표시하기 위해 사용하는 확장된 조인 방식입니다.
다시 말해, Inner Join은 두 테이블에 모두 데이터가 있어야만 결과가 나오지만, Outer Join은 한쪽에만 데이터가 있어도 결과가 나옵니다.
→ 찾는 조건이 NULL인 컬럼의 경우, 생략하지 않고 그 컬럼의 속성을 NULL로 채우고 가져옴
-
Oracle
조건절에서 NULL이 포함된 반대쪽 컬럼 (+)로 표현
SELECT <열 목록> FROM STUDENT s, PROFESSOR p WHERE s.advisor = p.pid(+);
-
ANSI
SELECT <열 목록> FROM <첫 번째 테이블(LEFT 테이블)> <LEFT | RIGHT | FULL> OUTER JOIN <두 번째 테이블(RIGHT 테이블)> ON <조인 조건> [WHERE 검색 조건]
Left Outer Join
상대 속성(오른쪽)이 없으면 NULL로 채우고 가져옵니다.
- 학생의 이름과 그 학생의 담당 교수를 출력
-
Oracle 방식
(+)
은 NULL이 포함된 컬럼의 반대쪽에 붙이면 됩니다.즉, Left Join을 표현하기 위해서는 반대쪽인 오른쪽에 작성하면 됩니다.
조인한 릴레이션을 보면 마치 pid가 NULL인 것처럼 표현되기에 없으면 NULL로 채워 가져오고 싶은 쪽에 (+)를 붙인다고 이해하면 쉬울듯 합니다.
SELECT s.sname, p.pname FROM STUDENT s, PROFESSOR p WHERE s.advisor = p.pid(+);
-
ANSI 방식
FROM
절에LEFT OUTER JOIN
을 명시해주면 됩니다. 이때,OUTER
은 생략이 가능합니다.SELECT s.sname, p.pname FROM STUDENT s LEFT JOIN PROFESSOR p ON s.advisor = p.pid;
- 조인 결과
sid | sname | advisor | gen | pid | pname |
---|---|---|---|---|---|
1 | Anna | 1 | F | 1 | John |
2 | Marie | 10 | F | 10 | Smith |
3 | Will | 10 | M | 10 | Smith |
4 | David | 20 | M | 20 | Jason |
5 | Micheal | NULL | M | NULL | NULL |
6 | Sophia | NULL | F | NULL | NULL |
만약 Outer join이 아닌 Inner join인 경우, advisor
이 NULL
인 5, 6번 컬럼은 조인 결과에 포함되지 않을 것입니다.
두 가지 방식 모두 학생 테이블의 advisor
컬럼이 NULL 경우에도 학생 이름을 출력함을 볼 수 있습니다.
Join 종류 정리
Join 종류 | 기호 | 기능 |
---|---|---|
Equi join | ⋈ | 두 릴레이션 간의 같은 값을 가진 집합 |
Theta | ⋈θ | 두 릴레이션 간의 비교 조건에 만족하는 집합 |
Natural | ⋈N | Equi 조인에서 중복 속성을 제거 |
Semi | ⋉ | Natural 조인 후 기호의 열린쪽의 속성을 제거 |
Left outer | ⟕ | Natural 조인 후 각각 왼쪽, 오른쪽, 양쪽의 모든 값을 결과로 추출 조인이 실패 또는 값이 없을 경우 한 쪽의 값을 NULL로 채용 |
Right outer | ⟖ | |
Full outer | ⟗ |