SQLite | 데이터 조인(Join) | 외부 조인 (OUTER JOIN 절)
2개의 테이블을 조인하여 데이터를 검색하는 방법 중에 지정된 각 테이블의 컬럼 값이 일치하는 데이터뿐만 아니라 어느 한쪽 테이블에만 데이터가 있어도 같이 받아오는 방법이 외부 조인이다. 여기에 외부 조인을 위한 LEFT OUTER JOIN 절 사용에 대해 설명한다.
외부 조인
먼저 외부 조인에 대해 간략하게 설명한다. 외부 조인은 두 테이블에 각각 결합이 되는 컬럼을 지정하고 각각의 컬럼에 같은 값이 저장되어 있는 데이터를 결합하여 받아온다. 내부 조인의 경우는 일치하지 않는 데이터를 검색하지 않았지만 외부 조인의 경우 일치하지 않는 경우도 데이터로 받아온다.
다음 그림을 보도록 하자. 왼쪽 테이블과 오른쪽 테이블을 외부 조인을 한다. 조인이 되는 컬럼은 왼쪽 테이블의 “부서 ID"와 오른쪽 테이블의 “ID"이다. 이 두 컬럼의 값이 같은 데이터를 조합하여 받아온다.
왼쪽 테이블의 데이터 중 “부서 ID"컬럼의 값이 오른쪽 테이블의 “ID” 컬럼의 값에 없는 경우에도 데이터를 받아온다.
주의 사항
외부 조인의 경우 왼쪽 테이블 밖에 없는 데이터도 받아 오는 방법을 왼쪽 외부 조인(LEFT OUTER JOIN ), 오른쪽 테이블 밖에 없는 데이터도 받아 오는 것을 오른쪽 외부 조인(RIGHT OUTER JOIN ), 왼쪽 테이블 밖에 없는 데이터와 오른쪽 테이블 밖에 없는 데이터도 모두 받아오는 것을 완전 외부 조인(FULL OUTER JOIN)이라고 한다.
다만, SQLite는 왼쪽 외부 조인을 하는 LEFT OUTER JOIN 절에서만 지원하고 있다. 오른쪽 외부 조인을 수행하는 RIGHT OUTER JOIN 절과 완전 외부 조인을 하는 FULL OUTER JOIN 절을 사용하려고하면 Error: RIGHT and FULL OUTER JOINs are not currently supported라는 에러가 발생하므로 주의하자.
LEFT OUTER JOIN 절 사용 방법
SELECT 문과 LEFT OUTER JOIN 절을 조합하여 두 테이블을 외부 조인시켜 데이터를 검색 할 수 있다. 형식은 다음과 같다.
SELECT 테이블명. 컬럼 명, ... FROM 테이블명1
LEFT OUTER JOIN 테이블명2
ON 테이블명1.컬럼명1 = 테이블명2.컬럼명2;
이를 단순화하면 다음과 같다.
SELECT (조회 컬럼) FROM 테이블명1
LEFT OUTER JOIN 테이블명2 ON (조인 조건);
SELECT 문에서 반환되는 데이터는 2개의 테이블을 조인하여 가져온다. 조회되는 컬럼은 두 테이블의 어떤 컬럼인지 알 수 있도록 “테이블명.컬럼명” 형식으로 지정한다. 조인 조건에는 조인이 되는 컬럼에 대해 “테이블명1.컬럼명1 = 테이블명2.컬럼명2"의 형식으로 지정한다.
외부 조인은 내부 조인의 경우와 비슷하지만, LEFT OUTER JOIN 절을 사용하는 경우 조인이 되는 컬럼의 값이 일치하는 데이터뿐만 아니라, 컬럼의 값이 FROM의 후에 작성된 테이블에 없어도 데이터로 가져온다.
–
간단한 예를 통해 어떻게 사용하는지에 대해 확인해 보자. 직원 목록이 등록된 employee 테이블과 부서가 등록된 dept 테이블을 만들고, INSERT 문을 사용하여 데이터도 같이 추가한다.
create table employee (id integer, name text, dept_id integer);
insert into employee values (1, 'dekuma', 1);
insert into employee values (2, 'kimkc', 3);
insert into employee values (3, 'araikuma', 1);
insert into employee values (4, 'happykuma', 2);
insert into employee values (5, 'mykuma', 4);
insert into employee values (6, 'raccoon', 3);
sqlite> create table employee (id integer, name text, dept_id integer);
sqlite>
sqlite> insert into employee values (1, 'dekuma', 1);
sqlite> insert into employee values (2, 'kimkc', 3);
sqlite> insert into employee values (3, 'araikuma', 1);
sqlite> insert into employee values (4, 'happykuma', 2);
sqlite> insert into employee values (5, 'mykuma', 4);
sqlite> insert into employee values (6, 'raccoon', 3);
sqlite>
create table dept (id integer, name text);
insert into dept values (1, 'Sales');
insert into dept values (2, 'Manage');
insert into dept values (3, 'Dev');
sqlite> create table dept (id integer, name text);
sqlite>
sqlite> insert into dept values (1, 'Sales');
sqlite> insert into dept values (2, 'Manage');
sqlite> insert into dept values (3, 'Dev');
sqlite>
–
그럼 먼저 employee 테이블에 dept 테이블을 외부 조인을 하여 데이터를 조회해 보자.
select * from employee left outer join dept on employee.dept_id = dept.id;
sqlite> select * from employee left outer join dept on employee.dept_id = dept.id;
id name dept_id id name
---------- ---------- ---------- ---------- ----------
1 dekuma 1 1 Sales
2 kimkc 3 3 Dev
3 araikuma 1 1 Sales
4 happykuma 2 2 Manage
5 mykuma 4
6 raccoon 3 3 Dev
sqlite>
내부 조인과 달리 외부 조인의 경우에는 FROM 바로 뒤에 작성된 테이블에만 있는 데이터를 조회하는데 있어서 테이블의 순서가 바뀌면 결과가 달라진다. 이전과는 반대로 dept 테이블에 employee 테이블을 외부 조인을 해보자.
select * from dept left outer join employee on dept.id = employee.dept_id;
sqlite> select * from employee left outer join employee on dept.id = employee.dept_id;
id name id name dept_id
---------- ---------- ---------- ---------- ----------
1 Sales 1 dekuma 1
1 Sales 3 araikuma 1
2 Manage 4 happykuma 2
3 Dev 2 kimkc 3
3 Dev 6 raccoon 3
sqlite>
dept 테이블에 employee 테이블을 외부 조인하면 dept 테이블에만 있는 데이터가 없어지므로, 내부 조인의 경우와 같은 결과가 조회되었다.
조회할 데이터 컬럼 지정 방법
조회할 데이터 컬럼 지정 방법은 내부 조인의 경우와 동일하다. 자세한 내용은 내부 조인의 “조회할 데이터 컬럼 지정 방법"을 참조하도록 한다. 두 테이블에서 동일한 컬럼명이 있는 경우 “테이블명.컬럼명"과 같이 지정하고 그 중 하나의 테이블 밖에 없는 컬럼명의 경우 테이블명을 생략하고 “컬럼명"으로 지정한다.
외부 조인의 경우도 실제로 해보도록 한다.
select employee.id, employee.name, dept.name from employee
left outer join dept on employee.dept_id = dept.id;
sqlite> select employee.id, employee.name, dept.name from employee
...> left outer join dept on employee.dept_id = dept.id;
id name name
---------- ---------- ----------
1 dekuma Sales
2 kimkc Dev
3 araikuma Sales
4 happykuma Manage
5 mykuma
6 raccoon Dev
sqlite>