혼자 공부하는 공간

[SQL기본 및 활용] 2020년 SQLD 내용 정리 :: SQL 기본 #9 본문

자격증/SQLD

[SQL기본 및 활용] 2020년 SQLD 내용 정리 :: SQL 기본 #9

god_z 2020. 8. 23. 15:23

<목차>


<< 조인 (JOIN) >>

* 지금까지는 하나의 테이블에서 데이터를 출력하는 것을 살펴보았다. 두 개 이상의 테이블들을 연결 또는 결합하여 데이터를 출력할 때 JOIN을 사용한다.

* 만약 A, B, C, D의 테이블이 조인될 때, 두 테이블을 조인 처리하고 그 결과와 또 다른 테이블을 조인 처리하는 식으로 두 개의 테이블만 조인 처리된다. (옵티마이저가 처리함.)


 

1. EQUI JOIN

* 두 개의 테이블 간에 칼럼 값들이 서로 정확하게 일치하는 경우에 사용되는 방법.

* 대부분 PK와 FK의 관계를 기반으로 한다.

* 조인의 조건은 WHERE 절에 기술하는데 "=" 연산자를 사용해서 표현.

 

* 예시

1
2
3
4
5
6
7
8
9
10
11
12
/* 기본 형태 */
SELECT 테이블1.칼럼명, 테이블2.칼럼명, ... 
FROM 테이블1, 테이블2 
WHERE 테이블1.칼럼명1 = 테이블2.칼럼명2;
/* WHERE 절에 JOIN 조건을 넣는다. */
 
 
/* ANSI/ISO SQL 표준 방식 */
SELECT 테이블1.칼럼명, 테이블2.칼럼명, ... 
FROM 테이블1 INNER JOIN 테이블2 
ON 테이블1.칼럼명1 = 테이블2.칼럼명2; 
/* ON 절에 JOIN 조건을 넣는다. */
cs

---> INNER JOIN 에서는 테이블의 순서가 결과에 영향을 미치지 않는다.

 

* 예시 - 문제

   : 선수 테이블과 팀 테이블에서 선수 이름과 선수가 소속된 팀의 이름을 출력하시오.

 

* 예시 - 결과

1
2
3
4
5
6
7
8
SELECT PLAYER.PLAYER_NAME 선수명, TEAM.TEAM_NAME 소속팀명 
FROM PLAYER, TEAM 
WHERE PLAYER.TEAM_ID = TEAM.TEAM_ID; 
 
/* INNER JOIN을 명시하여 사용할 수도 있다. */
SELECT PLAYER.PLAYER_NAME 선수명, TEAM.TEAM_NAME 소속팀명 
FROM PLAYER INNER JOIN TEAM 
ON PLAYER.TEAM_ID = TEAM.TEAM_ID;
cs

---> SELECT 절에 단순 칼럼명이 아닌 테이블명.칼럼명을 사용하는 이유

  1. 여러 테이블에서 칼럼명이 중복될 수도 있기 때문이다. 그렇게 되면 DBMS의 옵티마이저는 어떤 테이블의 칼럼을 사용해야 할지 모르기 때문에 에러가 발생한다.

  2. SQL 문의 가독성에 도움 : 어느 테이블의 어떤 칼럼인지 바로 볼 수 있기 때문에.

  3. 향후 같은 칼럼이 생성되거나 하는 미래에 발생할 에러를 방지하는 효과.

 

1-1. 선수-팀 테이블 EQUI JOIN 사례

EQUI JOIN을 설명하기 위한 선수-팀 테이블 관계도

* 예시 - 문제

   : 선수 테이블과 팀 테이블에서 K-리그 소속 선수들의 이름, 백넘버와 그 선수가 소속된 팀명과 연고지를 출력하라.

 

* 선수 테이블의 TEAM_ID(FK)와 팀 테이블에 있는 TEAM_ID(PK)의 관계를 통해 두 테이블을 재배열해서 알아보기 쉽게 만들 수 있다.

선수-팀 테이블의 데이터 재배열 후

 

* 예시 - 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
SELECT PLAYER.PLAYER_NAME, PLAYER.BACK_NO, PLAYER.TEAM_ID, TEAM.TEAM_NAME, TEAM.REGION_NAME 
FROM PLAYER, TEAM 
WHERE PLAYER.TEAM_ID = TEAM.TEAM_ID; 
 
/* INNER JOIN을 명시하여 사용할 수도 있다. */
SELECT PLAYER.PLAYER_NAME, PLAYER.BACK_NO, PLAYER.TEAM_ID, TEAM.TEAM_NAME, TEAM.REGION_NAME 
FROM PLAYER INNER JOIN TEAM 
ON PLAYER.TEAM_ID = TEAM.TEAM_ID;
 
/* SELECT 절이 길기 때문에 FROM 의 테이블에 ALIAS를 사용해서 SELECT을 줄일 수 있다. */
SELECT P.PLAYER_NAME, P.BACK_NO, P.TEAM_ID, T.TEAM_NAME, T.REGION_NAME
FROM PLAYER P, TEAM T 
WHERE P.TEAM_ID = T.TEAM_ID;
 
/*
PLAYER_NAME BACK_NO TEAM_ID TEAM_NAME    REGION_NAME 
----------- ------- ------- ------------ ----------- 
이고르       21      K06     아이파크     부산 
오비나       26      K10     시티즌       대전 
윤원일       45      K02     삼성블루윙즈  수원 
페르난도     44      K04     유나이티드    인천 
레오         45      K03     스틸러스     포항 
실바         45      K07     드래곤즈     전남 
무스타파     77      K04     유나이티드    인천 
에디         7       K01     울산현대     울산 
알리송       14      K01     울산현대     울산 
쟈스민       33      K08     일화천마     성남 
디디         8       K06     아이파크     부산 
480개 항이 선택되었다.
*/
cs

 

1-2. 선수-팀 테이블 WHERE 절 검색 조건 사례

* 위의 결과에서 WHERE 절에 추가적인 조건을 넣을 수 있다.

 

* 예시 - 문제

   : 위의 조건에서 포지션이 'GK' 인 선수를 백넘버 순으로 정렬하여 출력하라.

 

* 예시 - 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
SELECT P.PLAYER_NAME 선수명, P.BACK_NO 백넘버, T.REGION_NAME 연고지, T.TEAM_NAME 팀명 
FROM PLAYER P, TEAM T 
WHERE P.TEAM_ID = T.TEAM_ID AND P.POSITION = 'GK' 
ORDER BY P.BACK_NO;
 
/* INNER JOIN을 명시하여 사용할 수도 있다. */
SELECT P.PLAYER_NAME 선수명, P.BACK_NO 백넘버, T.REGION_NAME 연고지, T.TEAM_NAME 팀명 
FROM PLAYER P INNER JOIN TEAM T 
ON P.TEAM_ID = T.TEAM_ID 
WHERE P.POSITION = 'GK' 
ORDER BY P.BACK_NO;
 
/*
선수명  백넘버 연고지 팀명 
------- ----- ----- ---------
최종문   1     전남  드래곤즈 
정병지   1     포항  스틸러스 
박유석   1     부산  아이파크 
김승준   1     대전  시티즌 
이현     1     인천  유나이티드 
김운재   1     수원  삼성블루윙즈 
정해운   1     성남  일화천마 
권정혁   1     울산  울산현대 
최동석   1     서울  FC서울 
김창민   1     전북  현대모터스 
김용발   18    전북  현대모터스 
한동진   21    인천  유나이티드 
이은성   21    대전  시티즌 
김준호   21    포항  스틸러스 
조범철   21    수원  삼성블루윙즈 
....
43개 항이 선택되었다.
*/
cs

---> JOIN의 조건을 기술할 때 FROM 절의 테이블이 ALIAS로 작성되었다며, SELECT나 WHERE 절에서도 ALIAS를 사용해야 한다.

 

1-3. 팀-운동장 테이블 EQUI JOIN 사례

팀-운동장 테이블 관계도

* 예시 - 문제

   : 소속팀이 가지는 운동장의 정보를 소속팀 정보와 함께 출력하라.

 

* 예시 - 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* 기본 형태 */
SELECT TEAM.REGION_NAME, TEAM.TEAM_NAME, TEAM.STADIUM_ID, STADIUM.STADIUM_NAME, STADIUM.SEAT_COUNT 
FROM TEAM, STADIUM 
WHERE TEAM.STADIUM_ID = STADIUM.STADIUM_ID; 
 
/* INNER JOIN을 명시하여 사용할 수도 있다. */
SELECT TEAM.REGION_NAME, TEAM.TEAM_NAME, TEAM.STADIUM_ID, STADIUM.STADIUM_NAME, STADIUM.SEAT_COUNT 
FROM TEAM INNER JOIN STADIUM 
ON TEAM.STADIUM_ID = STADIUM.STADIUM_ID; 
 
/* 테이블 ALIAS 사용 */
SELECT T.REGION_NAME, T.TEAM_NAME, T.STADIUM_ID, S.STADIUM_NAME, S.SEAT_COUNT 
FROM TEAM T, STADIUM S 
WHERE T.STADIUM_ID = S.STADIUM_ID; 
 
/* INNER JOIN ALIAS 사용 */
SELECT T.REGION_NAME, T.TEAM_NAME, T.STADIUM_ID, S.STADIUM_NAME, S.SEAT_COUNT 
FROM TEAM T INNER JOIN STADIUM S 
ON T.STADIUM_ID = S.STADIUM_ID;
 
/*
REGION_NAME  TEAM_NAME    STADIUM_ID  STADIUM_NAME    SEAT_COUNT 
-----------  -----------  ----------  --------------  ---------- 
전북         현대모터스     D03        전주월드컵경기장  28000 
성남         일화천마       B02        성남종합운동장    27000 
포항         스틸러스       C06        포항스틸야드      25000 
전남         드래곤즈       D01        광양전용경기장    20009 
서울         FC 서울       B05        서울월드컵경기장   66806 
........
15개의 행이 선택되었다.
*/
cs

 

2. Non EQUI JOIN

* Non EQUI JOIN(비등가) JONI은 두 개의 테이블 간에 칼럼 값들이 서로 정확하게 일치하지 않는 경우에 사용된다.

* "=" 연산자가 아닌 BETWEEN, >, >=, <, <= 등과 같은 연산자들을 사용하여 JOIN을 수행한다.

 

* 참조 테이블

사원-급여등급 테이블의 관계도

 

* 예시 - 문제

   : 사원 모두에 대해서 급여와 급여에 해당하는 급여 등급을 출력하라.

 

* 예시 - 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SELECT E.ENAME 사원명, E.SAL 급여, S.GRADE 급여등급 
FROM EMP E, SALGRADE S 
WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL;
 
/*
사원명 급여 급여등급 
------ ---- ------ 
SMITH  800  1 
JAMES  950  1 
ADAMS  1100 1 
WARD   1250 2 
MARTIN 1250 2 
MILLER 1300 2 
TURNER 1500 3 
ALLEN  1600 3 
CLARK  2450 4 
BLAKE  2850 4 
JONES  2975 4 
SCOTT  3000 4 
FORD   3000 4 
KING   5000 5 
14개의 행이 선택되었다.
*/
cs

---> 데이터 모델에 따라서 Non EQUI JOIN이 불가능한 경우도 존재한다.

 

3. 3개 이상의 TABLE JOIN

선수-운동장-팀 테이블 관계도

* 예시 - 문제

   : 선수들 별로 홈그라운드 경기장 정보를 출력하라

---> 선수 테이블과 운동장 테이블은 상관관계가 없으므로 중간에 팀 테이블이라는 상관관계가 있는 테이블을 추가해서 3개의 테이블을 JOIN 해야한다.

---> 선수 테이블의 TEAM_ID가 팀 테이블의 TEAM_ID와 PK-FK의 상관관계에 있고, 운동장 테이블의 STADIUM_ID와 팀 테이블의 STADIUM_ID가 PK-FK 상관관계에 있다는 것을 이용.

(WHERE 절에 2개 이상의 JOIN 조건이 필요하다.)

 

* 예시 - 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* 기본 형태 */
SELECT P.PLAYER_NAME 선수명, P.POSITION 포지션, T.REGION_NAME 연고지, T.TEAM_NAME 팀명, S.STADIUM_NAME 구장명 
FROM PLAYER P, TEAM T, STADIUM S 
WHERE P.TEAM_ID = T.TEAM_ID AND T.STADIUM_ID = S.STADIUM_ID 
ORDER BY 선수명;
 
/* INNER JOIN 명시 */
SELECT P.PLAYER_NAME 선수명, P.POSITION 포지션, T.REGION_NAME 연고지, T.TEAM_NAME 팀명, S.STADIUM_NAME 구장명 
FROM PLAYER P INNER JOIN TEAM T 
ON P.TEAM_ID = T.TEAM_ID INNER JOIN STADIUM S 
ON T.STADIUM_ID = S.STADIUM_ID 
ORDER BY 선수명;
 
/*
선수명   포지션 연고지 팀명         구장명 
-------- ----- ----- ------------ ------------- 
가비      MF   수원   삼성블루윙즈  수원월드컵경기장 
가이모토  DF   성남   일화천마      성남종합운동장 
강대희    MF   수원   삼성블루윙즈  수원월드컵경기장 
강성일    GK   대전   시티즌        대전월드컵경기장 
강용      DF   포항   스틸러스      포항스틸야드 
강정훈    MF   대전   시티즌        대전월드컵경기장 
......
480개의 행이 선택되었다.
*/
cs

 

* JOIN의 필요성

   : 정규화는 불필요한 데이터의 중복을 줄이고, 데이터의 정합성을 유지하여 이상현상을 방지하는 모델링 기법이다. 그 결과로 테이블을 분할하기 때문에 여러 테이블의 데이터를 핸들링하기 위해서는 JOIN이 필수적이다.

 

* JOIN을 사용하지 않으면?

   : 하나의 테이블에 모든 데이터를 집중시키면 JOIN에 대한 비용은 없지만, 가장 중요한 데이터 정합성 유지에 더 많은 비용이 들어가게 된다.

   : 한 테이블에 데이터가 집중되는 경우, 방대한 데이터에서 검색하는 속도 자체가 떨어질 수도 있다.

   : JOIN은 비용에 대한 리스크가 존재하기 때문에 신중하게 작성해야 한다.

 

 

 

출처

http://www.dbguide.net/db.db?cmd=view&boardUid=148197&boardConfigUid=9&categoryUid=216&boardIdx=134&boardStep=1

 

데이터 전문가 지식포털 DBGuide.net

관계형 데이터베이스 개요 DDL DML TCL WHERE 절 함수(FUNCTION) GROUP BY, HAVING 절 ORDER BY 절 조인(JOIN) 1. JOIN 개요 지금까지는 하나의 테이블에서 데이터를 출력하는 것을 살펴보았다. 하지만, 이것은 일상

www.dbguide.net

질문은 댓글로 남겨주시면 되겠습니다. 감사합니다.

Comments