중복 데이터를 피하기 위해서 데이터를 쪼개 여러 테이블로 나눠서 저장된 관계형 데이터베이스에서 분리된 데이터를 원하는 결과로 도출하기 위해 여러 테이블을 조합하기 위해 컬럼 기준으로 행을 합쳐주는 연산
□ JOIN 예시
SELECT ...
FROM R, S
WHERE R.A <비교연산자> S.B;
다음과 같은 SELECT문은 릴레이션 R의 Attribute A와 릴레이션 S의 Attribute B를 비교연산자를 통해 조건을 만족하는 튜플들의 집합을 구한다.
R.A <비교연산자> S.B; 인 경우 R.A와 S.B는 주로 기본 키와 외래 키의 관계를 갖는다.
특징 |
- N개의 릴레이션을 연관시키기 위해서는 N-1개의 JOIN 조건이 필요하다. - JOIN 조건을 생략하거나 틀리게 표현한 경우 카티션 곱이 생성된다. |
SELECT * FROM Company.EMPLOYEE;
SELECT * FROM Company.DEPARTMENT;
- 셀프 조인
자기 자신의 테이블을 조인하는 방법
질의: 모든 사원에 대해서 사원의 이름과 직속 상사의 이름을 검색하고 월급이 많은 순서로 정렬하여 출력하시오.
SELECT E.EMPNAME as MENTEE, E.SALARY, M.EMPNAME as MENTO
from Company.EMPLOYEE E, Company.EMPLOYEE M
where E.MANAGER = M.EMPNO
order by E.SALARY DESC;
- 중첩 질의
외부 질의 안에 중첩된 쿼리문들을 중첩 질의라고 한다.
- 한 개의 스칼라 값이 반환되는 경우
select EMPNAME, TITLE
from Company.EMPLOYEE
where TITLE = (select TITLE from Company.EMPLOYEE where EMPNAME = "박영권");
-- EMPLOYEE 릴레이션에서 EMPNAME이 "박영권"인 사람의 직급과 같은 사람들을 EMPLOYEE 릴레이션에서 조회한다.
- 한 개의 Attribute로 이루어진 릴레이션이 반환된 경우
외부 질의의 WHERE절에서 IN, ANY(SOME), ALL, EXISTS 같은 연산자를 사용한다.
연산자 | 설명 |
IN | 한 Attribute가 값들의 집합에 속하는지 테스트할 때 사용 |
ANY | 하나 이상의 값들과 어떤 관계를 갖는지 테스트할 때 사용 |
EXISTS | 여러 Attribute로 이루어진 릴레이션이 반환되는 경우에 사용 |
ALL | 한 Attribute가 값들의 집합에 속하는 모든 값들과 어떤 관계를 갖는지 테스트할 때 사용 |
=, <>, <=, <>, >=, >의 비교연산자도 같이 사용 |
select EMPNAME, TITLE, DNO
from Company.EMPLOYEE
where DNO in (select DEPTNO from Company.DEPARTMENT where DEPTNAME = "영업" OR DEPTNAME = "개발");
-- 영업부나 개발부에 근무하는 사람들의 이름과 직급을 조회한다.
- 여러 Attribute들로 이루어진 릴레이션이 반환되는 경우
select EMPNAME
from Company.EMPLOYEE E
where EXISTS
(select *
from Company.DEPARTMENT D
where E.DNO = D.DEPTNO
AND (DEPTNAME = "영업" OR DEPTNAME = "개발"));
-- 영업부나 개발부에서 근무하는 사원들의 이름을 조회
- 상관 중첩 질의
위 EXISTS를 사용한 예시에서 외부 질의 from에서 명시된 EMPLOYEE릴레이션을 중첩 질의 WHERE에서 사용되므로 상관 중첩 질의가 적용된다.
- 내부 조인(INNER JOIN)
기본 테이블과 조인 테이블 모두 데이터가 존재해야 조회된다.
(교집합으로 생각하면 편하다)
-- 중첩 질의
select EMPNAME, TITLE, DNO
from Company.EMPLOYEE
where DNO in (select DEPTNO from Company.DEPARTMENT where DEPTNAME = "영업" OR DEPTNAME = "개발");
-- INNER JOIN
select EMPNAME, TITLE, DNO
from Company.EMPLOYEE as E
inner join Company.DEPARTMENT as D
on (E.DNO = D.DEPTNO) AND (D.DEPTNAME = "영업" OR D.DEPTNAME = "개발");
두 쿼리문의 결과 값은 같다.
- 외부 조인(OUTER JOIN)
내부 조인은 두 테이블에 모두 데이터가 있어야만 결과가 나오지만, 외부 조인은 한쪽에만 데이터가 있어도 결과가 조회된다.
SELECT <열 목록>
FROM <첫 번째 테이블(LEFT 테이블)>
<LEFT | RIGHT | FULL> OUTER JOIN <두 번째 테이블(RIGHT 테이블)>
ON <조인 조건>
[WHERE 검색 조건]
- LEFT OUTER JOIN
□ 교집합을 포함하는 경우
select EMPNAME, TITLE, DNO, DEPTNAME
from Company.EMPLOYEE as E
left outer join Company.DEPARTMENT as D
on (E.DNO = D.DEPTNO) AND (D.DEPTNAME = "영업" OR D.DEPTNAME = "개발");
□ 교집합을 포함하지 않는 경우 (DEPTNAME이 NULL인 경우를 제외)
select EMPNAME, TITLE, DNO, DEPTNAME
from Company.EMPLOYEE as E
left outer join Company.DEPARTMENT as D
on (E.DNO = D.DEPTNO) AND (D.DEPTNAME = "영업" OR D.DEPTNAME = "개발")
where D.DEPTNAME is NOT NULL
- RIGHT OUTER JOIN
select EMPNAME, TITLE, DNO, DEPTNAME
from Company.EMPLOYEE as E
right outer join Company.DEPARTMENT as D
on (E.DNO = D.DEPTNO) AND (D.DEPTNAME = "영업" OR D.DEPTNAME = "개발")
select EMPNAME, TITLE, DNO, DEPTNAME
from Company.EMPLOYEE as E
right outer join Company.DEPARTMENT as D
on (E.DNO = D.DEPTNO) AND (D.DEPTNAME = "영업" OR D.DEPTNAME = "개발")
where E.DNO is NULL
- FULL OUTER JOIN
MySQL에서는 FULL OUTER JOIN을 지원하지 않는다고 한다.. 머쓱..
LEFT, RIGHT OUTER JOIN의 결과값 모두 출력된다고 생각하면 된다.
- 상호 조인 (CROSS JOIN)
한쪽 테이블의 모든 행과 다른 쪽 테이블의 모든 행을 조인시키는 기능
상호 조인 결과의 전체 행 개수는 두 테이블의 각 행의 개수를 곱한 수만큼 생성된다.
카티션 곱이라고 부른다.
□ 양식
SELECT *
FROM <첫 번째 테이블>
CROSS JOIN <두 번째 테이블>
select EMPNAME, TITLE, DNO, DEPTNAME
from Company.EMPLOYEE as E
cross join Company.DEPARTMENT D
끝!
# 참고한 자료