SQLite | Joining Data | Outer Joins (OUTER JOIN)

An outer join returns matching rows from two tables and also unmatched rows from one side. This article explains LEFT OUTER JOIN.

Outer Joins

Like an inner join, an outer join matches values in specified columns. Unlike an inner join, it also returns unmatched rows.

In the diagram, the left table’s Department ID is matched with the right table’s ID.

Outer join

Rows from the left table are returned even when their Department ID has no matching ID in the right table.

Note
A LEFT OUTER JOIN retains unmatched left rows, a RIGHT OUTER JOIN retains unmatched right rows, and a FULL OUTER JOIN retains unmatched rows from both sides.

The SQLite version used here supports only LEFT OUTER JOIN; attempting RIGHT or FULL OUTER JOIN produces an unsupported-join error.

Using LEFT OUTER JOIN

Combine SELECT with LEFT OUTER JOIN to query two tables. The syntax is as follows.

SELECT table_name. column_name, ... FROM table_name1
  LEFT OUTER JOIN table_name2
  ON table_name1.column_name1 = table_name2.column_name2;

A simplified form is shown below.

SELECT (result_columns) FROM table_name1
  LEFT OUTER JOIN table_name2 ON (join_condition);

Qualify selected columns as table_name.column_name when necessary.   Write the join condition as table1.column1 = table2.column2.

A left outer join returns matched rows plus rows from the table after FROM that have no match.

Create employee and dept tables and insert sample data.

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> 

First, left-join dept to employee.

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> 

Table order matters because unmatched rows are retained from the table after FROM. Reverse the tables and run the join again.

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> 

Since dept has no unmatched rows, this result is the same as the inner join.

Selecting Result Columns

Select columns as with an inner join. Qualify names shared by both tables; unique names may omit the table prefix.

Apply this column selection to the outer join.

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>