What is the difference between an inner and an outer join in SQL? | by Kate Marie Lewis | Towards Data Science

Joins in SQL are used to combine the contents of different tables. You can specify how you want the data from tables to be joined in many ways, one of which is the type of join. There are four main types of joins: inner join, full outer join, left outer join and right outer join.
The major difference between inner and outer joins is that inner joins result in the intersection of two tables, whereas outer joins result in the union of two tables.
In this story, I will describe the difference between an inner join, full outer join, left outer join and right outer join. I will then go through an example using characters from Harry Potter to demonstrate the differences.
A Venn diagram is a helpful way to visualise the difference between an inner join and an outer join.
Inner joins result in the overlapping part of the Venn diagram of two datasets, whilst for full outer joins the outer parts of the Venn diagram will also be returned.
For an inner join, only the rows that both tables have in common are returned. However, for a full outer join, all rows from both tables are returned.
Left and right outer joins are useful if you want to get all the values from one table but only the rows that match that table from the other table.
So in a left outer join, all rows from the left table will be returned plus the rows that the right table had in common. In contrast, for a right outer join, all rows from the right table will be returned plus the rows that the left table had in common.
To run the code in this example I used PostgreSQL 9.6 in SQL Fiddle. Feel free to use that if you would like to try out running the code without setting up a complicated environment. I have simplified the output of the tables in the examples to remove duplicate columns just to make it clearer and easier to understand, so don’t be alarmed if you try it out and it looks a little bit different. I used PostgreSQL rather than MySQL for this story because MySQL does not use full outer joins.
Let’s assume that you are trying to join two tables of student grades from Hogwarts School of Witchcraft and Wizardry. These tables are called potions_class and charms_class. Each table has two columns containing the names of the students and grades.
CREATE TABLE charms_class (    student_name varchar(255),    charms_grade varchar(255));INSERT INTO charms_class (student_name, charms_grade)VALUES    ('Harry', 'C'),    ('Ron', 'D'),    ('Hermione', 'A'),    ('Luna', 'B'),    ('Neville', 'B');CREATE TABLE potions_class (    student_name varchar(255),    potions_grade varchar(255));INSERT INTO potions_class (student_name, potions_grade)VALUES     ('Harry', 'A'),    ('Ron', 'C'),    ('Hermione', 'B'),    ('Ginny', 'A'),    ('Draco', 'D');
charms_class
potions_class
Imagine that a dragon threatens Hogwarts castle. Only the students who are enrolled in both potions class and charms class are allowed to go out with the teachers to defend the school.
To find out which students are in both the charms class and the potions class and what their grades are in each class you would use an inner join on the tables charms_class and potions_class.
select * from charms_class INNER JOIN potions_class on charms_class.student_name=potions_class.student_name;
The resulting table would look like this:
In this example of an inner join, only Harry, Ron and Hermione take both charms and potions and so their grades for both classes are returned in the results. Note that students who are only enrolled in one but not the other class did not appear in the results.
Therefore only Harry, Ron and Hermione are allowed to face the dragon.
The Ministry of Magic only hires graduates who have completed both charms class and potions class. However there are not enough students with the required pre-requisites to fill all the roles, so the Ministry of Magic wants a list of students to speak with who are already enrolled in one class.
To find out which students are in either the charms class or the potions class, you would use a full outer join. Note that if the student is not enrolled in potions class the potions_grade value will be NULL, similarly if the student is not enrolled in charms class the charms_grade value will be NULL.
So any student that has a NULL value in one of the grades columns will be the ones that the Ministry of Magic want to contact.
select * from charms_class FULL OUTER JOIN potions_class on charms_class.student_name=potions_class.student_name;
The resulting table would look like this:
In this example of a full outer join, all the students are included in the resulting table. Only Harry, Ron and Hermione take both charms and potions and so their grades for both classes are returned in the results and there are no NULL values in their rows.
Ginny and Draco only have grades for potions because they did not take charms, so they are assigned NULL values for their charms grade. Luna and Neville only have grades for charms because they did not take potions, so they are assigned NULL values for their potions grade.
Therefore Ginny, Draco, Luna and Neville are all students who could take the extra class in order to be able to work at the Ministry of Magic after graduation.
There has been a prank pulled in the headmaster’s office and all of Professor Dumbledore’s furniture is floating on the ceiling. Students who take charms class and got a C grade or higher are under suspicion. However, students who are enrolled in potions class could not have been the culprits because their class was on a field trip at the time of the prank.
To find out which students are in charms class with a grade of C or higher and are not enrolled in potions class, we would join the charms_class table and the potions_class table using a left outer join. Note that if the student is not enrolled in potions class the potions_grade value will be NULL.
select * from charms_class LEFT OUTER JOIN potions_class on charms_class.student_name=potions_class.student_name;
The resulting table would look like this:
Only Harry, Ron and Hermione take both charms and potions and so their grades for both classes are returned in the results and there are no NULL values in their rows.
Luna and Neville only have grades for charms because they did not take potions, so they are assigned NULL values for their potions grade.
Ginny and Draco did not take charms, so they are not included in this results table.
Therefore the suspects for the prank in the headmaster’s office are Luna and Neville. They both got B grades for charms class and were not on the potions class field trip at the time of the incident.
Professor Snape runs a potions club that meets at the same time as the charms class. Only students who are enrolled in potions class but not enrolled in charms class will be available to attend the club.
To find out which students are in potions class and not in charms class you could use a right outer join. Note that if the student is not enrolled in charms class the charms_grade value will be NULL.
select * from charms_class RIGHT OUTER JOIN potions_class on charms_class.student_name=potions_class.student_name;
The resulting table would look like this:
In this example of a right outer join, only Harry, Ron and Hermione take both charms and potions and so their grades for both classes are returned in the results and there are no NULL values in their rows.
Ginny and Draco only have grades for potions because they did not take charms, so they are assigned NULL values for their charms grade.
Luna and Neville did not take potions, so they are not included in this results table.
Therefore only Ginny and Draco are available to be part of the potions club because they do not take charms class.
The join that I have used most as a data scientist is left outer joins. For example, I used to work with health data and would often aggregate procedure numbers by location. In that case, I would put the location table on the left and do a left join. This is because there could be some locations where I didn’t have any procedures and if I did an inner join I would lose those locations. Inner joins are more useful when you only want complete datasets without the addition of NULL values that outer joins bring. I rarely use full outer joins, unless all the data from the two tables being joined needs to be retained. Full outer joins can end up producing very large results tables, especially if there is not very much overlap between the tables that you are joining.
If there is a different SQL method that you would like explained please leave a comment below.
In addition to data, my other passion is painting. You can find my wildlife art at www.katemarielewis.com