[데이터베이스] #5 JOIN

September 24, 2023


Join 연산

릴레이션들의 공통 속성을 중심으로 두 개의 릴레이션을 함쳐 새로운 릴레이션을 생성

왜 Join이 필요한가? → 카테션 곱은 전체의 조합을 만들기 때문에 성능이 떨어짐

DB에서의 의미: 여러 테이블을 거쳐서 값 가져오기

Join끼리 비교

Inner Join

Inner Join은 테이블 간의 공통 요소 (교집합)를 중심으로 새로운 릴레이션으로 생성하는 조인입니다.

1

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) 가져오기

  1. Oracle 방식

    SELECT s.sname "학생이름", s.deptno "학과번호", d.dname "학과이름"
    FROM STUDENT s, DEPARTMENT d WHERE s.deptno = d.deptno;
  2. 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)

  1. 근무 시간이 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

  1. 직원의 급여 범위내에 해당하는 등급 출력

    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 조인과는 다르게 명시하지 않고도 암묵적으로 짧게 조인할 수 있습니다.

대신 주의할 점은 컬럼의 이름으로 연결하기 때문에 idname같이 흔한 컬럼 이름인 경우, 잘못 조인할 수도 있습니다.

Outer Join

이전의 Inner Join은 양측 컬럼 값 중 하나라도 NULL인 경우, =(equal) 결과가 거짓이 되어 NULL 값이 생략됩니다.

Outer Join은 조건에 해당하는 컬럼이 NULL이라서 생략되는 정보를 표시하기 위해 사용하는 확장된 조인 방식입니다.

다시 말해, Inner Join은 두 테이블에 모두 데이터가 있어야만 결과가 나오지만, Outer Join은 한쪽에만 데이터가 있어도 결과가 나옵니다.

→ 찾는 조건이 NULL인 컬럼의 경우, 생략하지 않고 그 컬럼의 속성을 NULL로 채우고 가져옴

  1. Oracle

    조건절에서 NULL이 포함된 반대쪽 컬럼 (+)로 표현

    SELECT <열 목록>
    FROM STUDENT s, PROFESSOR p
    WHERE s.advisor = p.pid(+);
  2. ANSI

    SELECT <열 목록>
    FROM <첫 번째 테이블(LEFT 테이블)>
    <LEFT | RIGHT | FULL>
        OUTER JOIN <두 번째 테이블(RIGHT 테이블)>
    ON <조인 조건>
    [WHERE 검색 조건]

Left Outer Join

상대 속성(오른쪽)이 없으면 NULL로 채우고 가져옵니다.


  • 학생의 이름과 그 학생의 담당 교수를 출력
  1. Oracle 방식

    (+)은 NULL이 포함된 컬럼의 반대쪽에 붙이면 됩니다.

    즉, Left Join을 표현하기 위해서는 반대쪽인 오른쪽에 작성하면 됩니다.

    조인한 릴레이션을 보면 마치 pid가 NULL인 것처럼 표현되기에 없으면 NULL로 채워 가져오고 싶은 쪽에 (+)를 붙인다고 이해하면 쉬울듯 합니다.

    SELECT s.sname, p.pname
    FROM STUDENT s, PROFESSOR p
    WHERE s.advisor = p.pid(+);

  1. 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인 경우, advisorNULL인 5, 6번 컬럼은 조인 결과에 포함되지 않을 것입니다.

두 가지 방식 모두 학생 테이블의 advisor 컬럼이 NULL 경우에도 학생 이름을 출력함을 볼 수 있습니다.

Join 종류 정리

Join 종류 기호 기능
Equi join 두 릴레이션 간의 같은 값을 가진 집합
Theta ⋈θ 두 릴레이션 간의 비교 조건에 만족하는 집합
Natural ⋈N Equi 조인에서 중복 속성을 제거
Semi Natural 조인 후 기호의 열린쪽의 속성을 제거
Left outer Natural 조인 후 각각 왼쪽, 오른쪽, 양쪽의 모든 값을 결과로 추출
조인이 실패 또는 값이 없을 경우 한 쪽의 값을 NULL로 채용
Right outer ​⟖
Full outer

Profile picture

이재원

이해하기 쉬운 코드를 작성하려 고민합니다.


© 2024 Won's blog Built with Gatsby