본문 바로가기

데이터 사이언스/SQL

[SQLD 학습 자료 요약] SQL 기본 및 활용 1.9. 조인 (JOIN)

본 문서의 내용은 한국데이터산업진흥원에서 펴낸 SQL 전문가 가이드를 기반으로 자격증 취득에 도움이 될 개념을 정리한 것입니다.

SQL 전문가 가이드
국내도서
저자 : 한국데이터산업진흥원
출판 : 한국데이터산업진흥원 2020.05.29
상세보기

 

9. 조인 (JOIN)

1. JOIN 개요

두 개 이상의 테이블 들을 연결 또는 결합하여 데이터를 출력하는 것을 JOIN 이라고 하며, 일반적으로 사용되는 SQL 문장의 상당수가 JOIN 이라고 생각하면 JOIN 의 중요성을 이해하기 쉬울 것이다.

 

일반적인 경우 행들은 PRIMARY KEY(PK)나 FOREIGN KEY(FK) 값의 연관에 의해 JOIN 이 성립된다. 하지만 어떤 경우에는 이러한 PK, FK 의 관계가 없어도 논리적인 값들의 연관만으로 JOIN 이 성립 가능하다.

 

한 가지 주의할 점은 FROM 절에 여러 테이블이 나열되더라도 SQL 에서 데이터를 처리할 때는 단 두 개의 집합 간에만 조인이 일어난다는 것이다. FROM 절에 A, B, C 테이블이 나열되었더라도 특정 2 개의 테이블만 먼저 조인 처리되고, 2 개의 테이블이 조인되어서 처리된 새로운 데이터 집합과 남은 한 개의 테이블이 다음 차례로 조인되는 것이다. 이때 테이블의 조인 순서는 옵티마이저에 의해서 결정되고 주요 튜닝 포인트가 된다.

 

조인이 발생할 수 있는 테이블 간의 관계도 (출처: SQL 전문가 가이드)

 


2. EQUI(등가) JOIN

EQUI(등가) JOIN 은 두 개의 테이블 간에 칼럼 값들이 서로 정확하게 일치하는 경우에 사용되는 방법으로 대부분 PK ↔ FK 의 관계를 기반으로 한다. 그러나 일반적으로 테이블 설계 시에 나타난 PK ↔ FK 의 관계를 이용하는 것이지 반드시 PK ↔ FK 의 관계로만 EQUI JOIN 이 성립하는 것은 아니다.

 

JOIN 의 조건은 WHERE 절에 기술하게 되는데 “=” 연산자를 사용해서 표현한다. 다음은 EQUI JOIN 의 대략적인 형태이다.

SELECT T1.COL, T2.COL
FROM T1, T2
WHERE T1.COL1 = T2.COL2;

 

 

같은 내용을 ANSI/ISO SQL 표준 방식으로 표현하면 아래와 같다. ON 절에 대해서는 2 장 1 절에서 자세히 다룬다.

SELECT T1.COL, T2.COL
FROM T1
	INNER JOIN T2 ON T1.COL1 = T2.COL2;

 

 

특정 컬럼에 대해 "테이블명.컬럼명"으로 명시하는 이유

  1. JOIN에 사용되는 두 테이블 내에 같은 컬럼명이 존재하는 경우, 파싱 단계에서 에러가 발생한다.
  2. SQL에 대한 가독성이나 유지보수성을 높이는 효과가 있다.

 

하나의 SQL 문장 내에서 유일하게 사용하는 칼럼명이라면 칼럼명 앞에 테이블 명을 붙이지 않아도 되지만, 현재 두 집합에서 유일하다고 하여 미래에도 두 집합에서 유일하다는 보장은 없기 때문에 향후 발생할 오류를 방지하고 일관성을 위해 유일한 칼럼도 출력할 칼럼명 앞에 테이블명을 붙여서 사용하는 습관을 기르는 것을 권장한다.

 

조인 조건에 맞는 데이터만 출력하는 INNER JOIN 에 참여하는 대상 테이블이 N 개라고 했을 때, N 개의 테이블로부터 필요한 데이터를 조회하기 위해 필요한 JOIN 조건은 대상 테이블의 개수에서 하나를 뺀 N-1 개 이상이 필요하다. 예를 들어, 테이블이 4개가 표시되어 있다면 JOIN 조건은 4-1=3개 이상이 필요하다.

 

테이블명이 길고 SQL의 복잡도가 높아지면 오히려 가독성이 떨어지기 때문에 테이블명 대신 ALIAS를 주로 사용한다. 단일 테이블을 사용하는 SQL 문장에서는 필요성은 없지만 사용하더라도 에러는 발생하지 않으며, 여러 테이블을 사용하는 조인을 이용하는 경우는 매우 유용하게 사용할 수 있다.

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;

 

 

추가로 WHERE 절에서 JOIN 조건 이외의 검색 조건에 대한 제한 조건을 덧붙여 사용할 수 있다. 즉, EQUI JOIN 의 최소한의 연관 관계를 위해서 테이블 개수 - 1 개의 JOIN 조건을 WHERE 절에 명시하고, 부수적인 제한 조건을 논리 연산자를 통하여 추가로 입력하는 것이 가능하다.

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;

 

 

JOIN 조건을 기술할 때 주의해야 할 사항이 한 가지 있다. 만약 테이블에 대한 ALIAS 를 적용해서 SQL 문장을 작성했을 경우, WHERE 절과 SELECT 절에는 테이블명이 아닌 테이블에 대한 ALIAS를 사용해야 한다는 점이다. 그러나, 권장 사항은 아니지만 하나의 SQL 문장 내에서 유일하게 사용하는 칼럼명이라면 칼럼명 앞에 ALIAS 를 붙이지 않아도 된다.

SELECT REGION_NAME,     -- 유일한 컬럼의 경우 Alias를 사용하지 않을 수 있음
       TEAM_NAME,
       T.STADIUM_ID,
       STADIUM_NAME,
       SEAT_COUNT
FROM TEAM T,
     STADIUM S
WHERE T.STADIUM_ID = S.STADIUM_ID;

 

 

FROM 절에서 테이블에 대한 ALIAS 를 정의했는데, SELECT 절이나 WHERE 절에서 테이블명을 사용한다면 DBMS 의 옵티마이저가 칼럼명이 부적합하다는 에러를 파싱 단계에서 발생시킨다.

SELECT PLAYER.PLAYER_NAME 선수명,  -- FROM 절과 다른 Alias 사용하여 "ERROR 발생"
       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;

 


3. Non EQUI JOIN

Non EQUI(비등가) JOIN 은 두 개의 테이블 간에 칼럼 값들이 서로 정확하게 일치하지 않는 경우에 사용된다. Non EQUI JOIN 의 경우에는 “=” 연산자가 아닌 다른(Between, >, >=, <, <= 등) 연산자들을 사용하여 JOIN 을 수행하는 것이다.

 

대부분 Non EQUI JOIN을 수행할 수 있지만, 때로는 설계상의 이유로 불가능한 경우도 있다.

 

두 개의 테이블 간에 칼럼 값들이 서로 정확하게 일치하지 않는 경우에는 EQUI JOIN 을 사용할 수 없다. 이런 경우 Non EQUI JOIN 을 시도할 수 있으나 데이터 모델에 따라서 Non EQUI JOIN 이 불가능한 경우도 있다.

 

Non EQUI JOIN이 발생하는 테이블 관계도 (출처: SQL 전문가 가이드)

사원(EMP) 테이블에서 사원들의 급여가 급여등급(SALGRADE) 테이블의 등급으로 표시되기 위해서는 “=” 연산자로 JOIN 을 이용할 수가 없다.

 

SELECT E.ENAME 사원명, E.SAL 급여, S.GRADE 급여등급
FROM EMP E,
     SALGRADE S
WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL;

Non EQUI JOIN 수행 결과

 

 

BETWEEN a AND b 와 같은 SQL 연산자 뿐만 아니라 “=” 연산자가 아닌 “>”나 “<”와 같은 다른 연산자를 사용했을 경우에도 모두 Non EQUI JOIN 에 해당한다.

SELECT COUNT(*) CNT
FROM EMP_TBL A, RULE_TBL B
WHERE A.ENAME LIKE B.RULE


--  SQL 문 수행 결과
| EMPNO | ENAME | RULE |
------------------------
| 1000  | SMITH | S%   |
| 1100  | SCOTT | S%   |
| 1000  | SMITH | %T%  |
| 1100  | SCOTT | %T%  |

 


4. 3개 이상 TABLE JOIN

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 선수명;

3개의 테이블 조인 결과

 

 

선수 테이블과 운동장 테이블이 서로 관계가 없으므로 중간에 팀 테이블이라는 서로 연관관계가 있는 테이블을 추가해서 세 개의 테이블을 JOIN 해야만 원하는 데이터를 얻을 수 있다.

 

JOIN 이 필요한 기본적인 이유는 정규화에서부터 출발한다. 정규화란 불필요한 데이터의 정합성을 확보하고 이상현상(Anomaly) 발생을 피하기 위해, 테이블을 분할하여 생성하는 것이다. 특정 요구조건을 만족하는 데이터들을 분할된 테이블로부터 조회하기 위해서는 테이블 간에 논리적인 연관관계가 필요하고 그런 관계성을 통해서 다양한 데이터들을 출력할 수 있는 것이다. 그리고, 이런 논리적인 관계를 구체적으로 표현하는 것이 바로 SQL 문장의 JOIN 조건인 것이다.

 


↓SQL 전문가 가이드 요약 목록

더보기

 

따로 PDF 파일이 필요하신 분은 댓글을 통해 메일 주소 적어주시기 바랍니다.