데이터베이스

Join

Leo.K 2022. 4. 20. 18:19

이번 글은 앞 내용과 이어지기 때문에 이해가 어려우신 분들께서는 아래 링크의 내용을 먼저 보시기 바랍니다.

https://cm-me0410.tistory.com/4

Join의 개념

Join연산자의 기본개념을 파악해보도록 하겠습니다. 

1. 둘 이상의 테이블을 연결하여 데이터를 검색하는 방법입니다. 

2. 연결하는 기준을 "조인 기준"이라고 하며, 각 테이블의 공통된 값을 통해 연결하는데, 보통 기본키(PK) 및 외래키(FK) 값을 사용하여 연결합니다. 

3. 두 개의 테이블을 SELECT 문장 안에서 조인하여 조회하려면, 적어도 하나의 컬럼이 두 테이블 사이에서 공유되어야 합니다. [2번에서 말한 기본키 및 외래키가 그 역할을 합니다.]

 

Join의 종류를 설명하기 위해서 sawon, gogek, dept 세 개의 연습용 DB를 활용하였습니다.

연습용 DB

 

Join의 종류

조인의 종류로는 여러 가지가 있는데, 자주 사용하는 조인의 종류 몇 가지만 설명하도록 하겠습니다.

 

1. Inner Join

가장 일반적으로 사용되는 "="연산자를 사용한 조인입니다. 

두 테이블에서 "="연산자를 통해 만들어진 "조인 조건"을 만족하는 행들만이 1 : 1로 연결됩니다. 

아래 간단한 예시를 보고 설명하겠습니다.

Inner Join을 사용하면 조인조건을 만족하는 각 테이블의 행이 1:1로 연결

 

 

위의 연산 결과를 도출하기 위한 SQL문을 먼저 작성하고 설명을 이어가도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
--1번 형식
select 
     *
from dept d, sawon s
where d.deptno = s.deptno
     
--2번 형식 [ANSI-92 SQL]
select 
     *
from dept d inner join sawon s on d.deptno = s.deptno
 
cs

1번과 2번은 같은 결과를 도출합니다. 데이터베이스를 조작하는 DBMS의 종류 또한 만든 회사마다 달라서 MySql, MongoDB, Oracle 등의 종류가 있지만 각각의 DBMS마다 명령어의 형식이 약간씩 다릅니다. (C언어와 Java의 문법이 조금씩 다른 것이라고 생각하시면 됩니다.) 

그리하여 중구난방으로 다른 문법을 사용자가 편리하게 사용할 수 있도록 ANSI협회에서 공통으로 정의한 형식이 2번입니다. 2번 형식은 표준화된 문법이므로 어떤 DBMS에서도 성립합니다. 하여 필자는 Oracle을 사용하고 있지만 표준화된 문법으로 설명하겠습니다.

 

다시 그림으로 돌아가서 

sawon테이블의 1번 레코드 장동건의 부서 번호는 40번이고, dept테이블을 보니 40번의 부서명은 관리부이고 위치는 404입니다. 

연산 결과는 그림의 가장 최하단에 있습니다. 

보시는 바와 같이 Inner Join을 사용하면 조인 조건을 만족하는 각 테이블의 행이 1:1로 연결이 됩니다.

2. Outer Join

흔히, 외부 조인이라고 부르며, 외부 조인의 종류는 다음과 같습니다. 

A Left  Outer Join B

기준이 되는 릴레이션은 모든 행을 추출하고, 기준이 아닌 다른 행은 조인 조건을 만족하는 행만을 추출합니다.

이때, 기준은 outer join 앞에 나오는 "left", "right", "full"을 지칭합니다. 단순하게 왼쪽이면 "left", 오른쪽이면 "right"

정확한 연산 순서는 다음과 같습니다. 

1. 조건에 맞는 행이 먼저 결합되어 출력됩니다. 

2. 조건에 맞지 않는 행은 null값으로 이루어진 빈 행으로, 조인의 기준인 A 릴레이션의 행에 결합됩니다.

 

A Right Outer Join B 

연산 방식은 위와 같고, 조인의 기준만 위와 달리 Right가 되므로 생략하겠습니다.

 

글로만 보면 이해가 어려우니 간단한 그림을 통해 예시를 들어보겠습니다.

전체 데이터를 보기엔 가독성이 떨어질 것을 고려해 연산 결과의 특정 데이터만 발췌해왔습니다. 

 

사원 테이블과 고객 테이블을 left outer조인을 사용한 결과입니다. 

조인 조건으로는 사원 테이블의 사원 번호와 고객 테이블의 담당자 사원번호가 같은 데이터만 가져오라는 내용입니다.

 

결과를 보시면 다른 데이터들과 달리 사번이 6번인 영덕스는 고객 테이블의 내용이 null로 이루어진 빈행과 연결되어 있습니다.

이는 영덕스라는 사람이 담당하는 고객이 없다는 뜻입니다.

(테이블의 관계가 제대로 이해 안 되시는 분들은 이전 포스팅에서 테이블 간의 관계를 파악하고 오시길 바랍니다.)

이러한 결과는 left outer join으로 인한 결과입니다. 

조건에 맞지 않는 행도 그냥 빈 행으로 Left(기준 릴레이션)에 연결하라고 연산이 지정되어 있기 때문입니다.

 

하지만 같은 연산을 외부 조인이 아닌 내부 조인(inner join)으로 하면 어떻게 될까요? 

내부 조인은 반드시 조인 조건에 만족하는 행들만 1:1로 연결하기 때문에, 

담당하는 고객이 없는 사원 즉, 조인 조건을 만족하지 못하는 사원은 결과에 표출되지 않습니다. 

 

따라서, 조인을 하는 경우에는 어떤 데이터를 추출하고 어떤 데이터를 추출하지 않을지 확실하게 정해두고 

그에 따라 적절한 조인 방법을 사용해야 합니다.  

 

A Full  Outer Join B

1. 조건에 맞는 행이 먼저 결합됩니다. 

2. 왼쪽 오른쪽 릴레이션 모두 조건에 맞지 않는 행은 빈 행으로 연결됩니다. 

 

full outer join은 위의 두 개에 비해서 자주 사용되지 않기 때문에 간단한 예시로 설명하겠습니다.

위와 같이 간단한 릴레이션 A, B가 있을 때 full outer조인을 하면 기본적으로 모든 A의 데이터와 모든 B의 데이터가 추출됩니다. 조인 조건을 만족하지 못하는 데이터는 null로 이루어진 빈 행과 연결이 됩니다. 

자세한 내용은 위의 그림을 참고하시어 차이점을 구분하시기 바랍니다.

 

3. Cross Join

크로스 조인은 비교적 단순한 조인입니다. 조인을 위해 필요한 조건 없이 무조건적인 연결이 사용되는 Join입니다.

크로스 조인을 이용하면 Cartesian Product(카티션 프로덕트) 값을 얻을 수 있습니다. 

릴레이션 R의 행수는 4, 열수는 3이고, 릴레이션 S의 행수는 3, 열수는 5라고 가정해보겠습니다. 

[연습용 DB로 크로스 조인을 하면 연산의 특성상 너무 많은 데이터가 나오므로 엑셀로 급조한 테이블을 만들겠다.]

결과부터 보자면 릴레이션 R과 S의 크로스 조인으로 생성된 새로운 릴레이션 K는

(3+5) 8행, (4*3) 12열의 구조를 갖습니다.

조인하는 조건이 없기 때문에 모든 행들이 교차로 연결되어서 추출됩니다.

 

 

4. Self   Join

마지막으로 Self Join을 설명하고 마무리하도록 하겠습니다. 

이름에서 느껴지는 그대로 Self Join이란 자기 자신과의 조인을 하는 방법입니다. 

조인의 공통적인 개념은 둘 이상의 테이블을 공통적인 속성으로 연결한다고 했습니다.

즉, 사원 테이블과 사원 테이블을 조인하는 것이 바로 자기 자신과 조인을 하는 Self조인의 개념입니다.

그렇게 어려운 개념이 아니고 필요에 따라 사용하는 방법이므로 간단한 예시와 함께 마무리하겠습니다. 

사원테이블의 원본 데이터

 

Ex)

테이블을 구성하는 데이터를 살펴보면 SAMGR은 해당 사원의 사수(직속 상사)의 사원번호를 가리킵니다.

헌데 사용자는 원본 데이터에서 해당 사원의 직속 상사에 대한 정보를 추가해서 조회하고 싶어 합니다. 

이러한 경우에 셀프 조인을 사용합니다. 

 

결과적으로 우리가 조인을 사용하는 이유는 바로 현재 테이블에서 추출할 수 없는 데이터 필드를 다른 테이블에서 가져오기 위해 둘 이상의 테이블을 하나로 합쳐서 출력을 합니다. 

그 개념을 위의 예시에 적용해보겠습니다. 

사용자가 알고 싶은 정보는 사원에 대한 기본적인 정보와 함께 해당 사원의 상사 정보 또한 이어서 보고 싶은 것입니다.

헌데 원본 데이터는 위와 같이 사용자의 요구를 만족할 수 없습니다. 

따라서 사원 테이블과 사원 테이블을 Self join을 진행할 것인데, 이해를 돕기 위해 alias를 사용하여 앞의 테이블을 사원 정보를 담는 테이블로 s1, 뒤의 테이블을 상사 정보를 담는 상사 테이블로 s2라고 명명해주겠습니다.

 

1. self join + inner join

구현을 위한 소스코드는 다음과 같습니다.

1
2
3
4
5
6
select 
          s1.sabun, s1.sajob, s1.saname, --사원정보
          s2.sabun, s2.sajob, s2.saname  --상사정보
from sawon s1, sawon s2
where s1.samgr = s2.sabun 
order by s1.sabun
cs

셀프 조인의 경우 같은 테이블로 비교를 수행하기 때문에 반드시 앨리어스를 사용해서 조회하고자 하는 데이터의 필드명을 명시해주어야 합니다. (s1.sabun, s2.sabun...)

 

사원 테이블의 상사 번호와 상사 테이블의 사원번호가 일치하는 행을 1:1로 연결하여 결합한 후 조회한 경우입니다. 결과는 다음과 같습니다.

조회된 데이터를 보면 사원 테이블의 정보에 자신의 상사 정보가 연결돼서 추출된 것을 확인할 수 있습니다.

 

self join + inner join을 사용한 경우 위에 결과를 보시다시피

상사가 없는 각 부서의 부장급들은 생략되어 조회되었습니다.

 

혹여나 모든 사원들의 정보를 기반으로 하고,

상사 정보를 추가하고 싶다면 위에서 배운 left outer join을 사용하면 됩니다.

 

방식에 대한 설명은 위에서 충분히 하였기 때문에 별도의 설명 없이 참고용으로 코드와 결과만 첨부하도록 하겠습니다.

2. self join + left outer join

1
2
3
4
select 
      s1.sabun, s1.sajob, s1.saname, --사원정보
      s2.sabun, s2.sajob, s2.saname  --상사정보
 from sawon s1 left outer join sawon s2 on s1.samgr = s2.sabun
cs

 

 

아래의 결과를 보면 위에서 나왔던 결과와는 달리 모든 사원의 정보를 기반으로 데이터가 연결되어 출력된 것을 확인할 수 있습니다.

 

'데이터베이스' 카테고리의 다른 글

Tomcat다운로드&환경설정_HTML_국비_DAY40  (0) 2022.04.26
JDBC 실습_국비_DAY39  (0) 2022.04.22
DB 모듈화  (0) 2022.04.22
JDBC의 사용법  (0) 2022.04.21
ERD(Entity_Relation_Diagram)  (0) 2022.04.20