SQLite | 데이터 조인(Join) | 내부 조인 (INNER JOIN 절)

2개의 테이블을 조인하여 데이터를 검색하는 방법 중에 지정된 각 테이블의 컬럼 값이 일치하는 데이터만 검색하는 방법이 내부 조인이다. 여기에 내부 조인을 위한 INNER JOIN 절 사용에 대해 설명한다.

내부 조인

먼저 내부 조인에 대해 간략하게 설명하겠다. 내부 조인은 두 테이블에 각각 조인이 되는 컬럼을 지정하고 각각의 컬럼에 같은 값이 저장되어 있는 데이터를 조인하여 받아온다.

다음 그림은 보세요. 왼쪽 테이블과 오른쪽 테이블을 내부 조인한다. 조인이 되는 컬럼은 왼쪽 테이블의 “부서 ID"와 오른쪽 테이블의 “ID"이다. 이 두 컬럼의 값이 같은 데이터를 조합하여 받아온다.

inner join

왼쪽 테이블의 데이터 중에 “부서 ID” 컬럼의 값이 오른쪽 테이블의 “ID” 컬럼의 값에 없는 경우에는 데이터를 받아오지 않았다.

INNER JOIN 절 사용법

SELECT 문와 INNER JOIN 절을 조합하여 두 테이블을 내부 조인시켜 데이터를 받아온다. 형식은 다음과 같다.

SELECT 테이블명. 컬럼명, ...FROM 테이블명1
  INNER JOIN 테이블명2
  ON 테이블명1.컬럼명1 = 테이블명2. 컬럼명2;

길어서 이를 단순화하면 다음과 같다.

SELECT (얻을 컬럼) FROM 테이블명1
  INNER JOIN 테이블명2 ON (조인 조건);

SELECT 문에서 반환되는 데이터는 2개의 테이블을 조인하여 가져온다. 조회되는 컬럼은 두 테이블의 어떤 컬럼인지 알 수 있도록 “테이블명.컬럼명” 형식으로 지정한다.   조인 조건에는 조인이 되는 컬럼에 대해 “테이블명1.컬럼명1 = 테이블명2.컬럼명2"의 형식으로 지정한다.

간단한 예를 통해 어떻게 사용하는지에 대해 확인해 보자. 직원 목록이 등록된 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> 

다음은 어느 테이블에 어느 테이블을 조인할 것인지를 결정해야 한다. 내부 조인의 경우 조인 조건이 같다면 두 테이블을 먼저 작성되어도 결과는 동일하다.

select * from x inner join dept on (조인 조건);
select * from employee inner join employee on (조인 조건);

다음 조인 조건이다. 내부 조인하려면 두 테이블에서 조인이 되는 컬럼을 지정한다. 이번에는 employee 테이블의 dept_id 컬럼과 dept 테이블의 id 컬럼이 대상이 된다.

select * from employee inner join dept on employee.dept_id = dept.id;

  그럼 실제로 두 테이블을 내부 조인하여 데이터를 가져와 보자. 처음에는 employee 테이블에 dept 테이블을 내부 조인합니다.

select * from employee inner join dept on employee.dept_id = dept.id;
sqlite> select * from employee inner 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    
6           raccoon     3           3           Dev       
sqlite> 

이번에는 반대로 dept 테이블에 employee 테이블을 내부 조인한다.

select * from dept inner join employee on dept.id = employee.dept_id;
sqlite> select * from dept inner 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> 

받아온 조회 데이터의 컬럼 순서는 다르지만 받아온 데이터 자체는 동일하다.

조회할 데이터 컬럼 지정 방법

SELECT 문에서 SELECT 컬럼명1, 컬럼명2, …과 같이 작성하지만 테이블을 조인하면 하나의 데이터에 여러 데이터의 컬럼을 포함할 수 있다. 여러 테이블에서 같은 컬럼명을 사용하는 경우도 있기 때문에, 테이블을 조인한 경우에는 단순 “컬럼명” 대신에 “테이블명. 컬럼명"과 같이 지정한다.

앞의 예제에서 컬럼명 지정하지 않고, 데이터를 검색하면 다음과 같이 된다.

select * from employee inner join dept on employee.dept_id = dept.id;
sqlite> select * from employee inner 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    
6           raccoon     3           3           Dev       
sqlite> 

조회한 데이터의 컬럼은 id 컬럼 2개, name 컬럼도 2개 포함되어 있다. 이처럼 여러 테이블에 같은 이름의 컬럼이 있는 경우에 이 컬럼을 지정하여 조회하고자 하는 경우에는 다음과 같이 “테이블명. 컬럼명"의 형태로 지정한다.

select employee.id, employee.name, dept.name from employee
  inner join dept on employee.dept_id = dept.id;
sqlite> select employee.id, employee.name, dept.name from employee
   ...>   inner join dept on employee.dept_id = dept.id;
id          name        name      
----------  ----------  ----------
1           dekuma      Sales     
2           kimkc       Dev       
3           araikuma    Sales     
4           happykuma   Manage    
6           raccoon     Dev       
sqlite> 

특정 테이블 밖에 포함되지 않아서 테이블명을 생략해도 어느 테이블의 컬럼인지 알 수 있는 경우에는 “테이블명” 부분을 생략하고 “컬럼명"만으로도 가능한다. 아래에서는 dept_id 컬럼이 이에 해당한다.

select employee.id, employee.name, dept_id, dept.name from employee
  inner join dept on employee.dept_id = dept.id;
sqlite> select employee.id, employee.name, dept_id, dept.name from employee
   ...>   inner join dept on employee.dept_id = dept.id;
id          name        dept_id     name      
----------  ----------  ----------  ----------
1           dekuma      1           Sales     
2           kimkc       3           Dev       
3           araikuma    1           Sales     
4           happykuma   2           Manage    
6           raccoon     3           Dev       
sqlite> 

두개의 테이블에 동일한 컬럼명이 있는데 테이블명을 지정하지 않고 컬럼명만을 작성하면 다음과 같이 “Error: ambiguous column name: name” 컬럼명 에러가 발생한다.

select name from employee inner join dept on employee.dept_d = dept.id;
sqlite> select name from employee inner join dept on employee.dept_id = dept.id;
Error: ambiguous column name: name
sqlite>