DEV Community

Cover image for The SQL Savant: Inner Joins in SQL
Joy Ada Uche
Joy Ada Uche

Posted on • Edited on

14 2

The SQL Savant: Inner Joins in SQL

Ever tried retrieving the data you need from just one table but suddenly realised you need more detail or information about these data which you must get from another table? Joins to the rescue!!!
You can get that additional detail you need using the power of Joins. With Joins in SQL, you can retrieve or access the information you need from two or more tables.

Let’s say we are at a Javascript college and they just hired a new teacher who wishes to carry every student along in his class and then he requested the academic detail of every student and these details are located in different tables. This certainly sounds like a task for Joins right?

Assuming this class maintains a database consisting of 3 tables such as person, grade, and activity. We would most likely have to get the information we need by looking up data in the person and grade tables using joins.

But here comes a pool of questions. How do we get the needed information using joins? What if there are students without grades? Does the teacher want to see only students with grades or all students whether there is a grade or not? Well, it actually depends on how this new Javascript teacher wants it right? So, we had a meeting with him and he wants to see only students with grades. It is in this light we introduce the main types of Joins. They are:

  • The inner joins and
  • The outer joins

This class has a database with the person and grade tables as below:

person table

id name
11AA Adebayo
22BB Chioma
33CC Zamani
44DD Ayo
55EE Ahmad

grade table

grade_id person_id score year
111 33CC C 2020
112 33CC B 2019
221 44DD A 2020
222 44DD B 2019
view raw 1.md hosted with ❤ by GitHub

THE INNER JOIN (which is the most common type of join), also referred to as JOIN, is a type of JOIN that returns all rows from both participating tables where the key record of one table is equal to the key records of another table. Using an inner join on the person and grade table will return only students with grades like below:

id name score year
33CC Zamani C 2020
33CC Zamani B 2019
44DD Ayo A 2020
44DD Ayo B 2019
view raw 2.md hosted with ❤ by GitHub

In 2.md above, you can see that the inner join has combined both tables ON key columns (which has values) that are common to both tables. It then returns records that contain the selected columns in the SELECT clause - You can see in 1.md, that the id field for person table and person_id field for grade table matches for values of 33CC and 44DD only.

The code for completing an INNER JOIN from the person table to the grade table based on the common values of the key field is shown below:

SELECT id, name, score, year
FROM person
INNER JOIN grade
ON person.id = grade.person_id;
view raw 3.sql hosted with ❤ by GitHub

In 3.sql and 2.md, please note the following:

3.sql:

  • In the SELECT clause, the fields or columns you want to be returned from the tables are listed.
  • The person table is conventionally called the left table because it is the first table in the SELECT clause.
  • The grade table is conventionally called the right table because it is the table you are joining on.
  • The INNER JOIN keyword can be replaced with the JOIN keyword - INNER JOIN is the default if you don't specify the type when you use the word JOIN.
  • The ON clause introduces the key fields from each table we would be joining on. The ON clause is used to specify a join condition or a join-predicate. The name of a key field or key column can be the same or vary from one table to another - the key field name in the grade table, person_id, can also be named id like in the person table as long as it does not conflict with other column names in the grade table.

2.md:

  • Regardless of whether the value of the key field appears multiple times in a table, as far as it appears in both tables, the record would be included in the result e.g 33CC is returned twice for the year 2019 and 2020 respectively.

So, we can gladly use the inner join above and give the new teacher what he asked for.

An ad-hoc request comes in! The new teacher wants to see students with grades along with their yearly activities. Herein lies the awesomeness of SQL- the ability to combine multiple joins in a single query - Multiple Joins. Ring a bell? Let us see an example below:

person table

id name
11AA Adebayo
22BB Chioma
33CC Zamani
44DD Ayo
55EE Ahmad

grade table

grade_id person_id score year
111 33CC C 2020
112 33CC B 2019
221 44DD A 2020
222 44DD B 2019

activity table

activity_id person_id activity year
556 33CC bicycling 2020
667 44DD dancing 2019
778 11AA swimming 2020
999 33CC football 2019
view raw 4.md hosted with ❤ by GitHub

In 4.md above, we have 3 tables - person, grade and activity - an additional table, activity, which shows the hobbies a student partake in yearly. So we came up with the query below:

SELECT name, score, activity, activity.year
FROM person
INNER JOIN grade
ON person.id = grade.person_id
INNER JOIN activity
ON person.id = activity.person_id;
view raw 5.sql hosted with ❤ by GitHub

In 5.sql above, activity.year i.e table_name.column_name is used because the field year is common to the grade and activity tables. If the table_name is not specified, an error would be thrown saying it is ambiguous. So, 5.sql returns:

name score activity year
Zamani C football 2020
Zamani C bicycling 2019
Zamani B football 2020
Zamani B bicycling 2019
Ayo A dancing 2020
Ayo B dancing 2020
view raw 6.md hosted with ❤ by GitHub

Take a second look at this result! Do you observe something wrong with it? Some score field values are wrongly paired with activity and year values - Zamani for example, the 3rd and 4th rows are incorrect. This is so because we did not join on an extra key field, year, which is common to the activity and grade tables. So we modify the query to be:

SELECT name, score, activity, activity.year
FROM person
INNER JOIN grade
ON person.id = grade.person_id
INNER JOIN activity
ON person.id = activity.person_id
AND grade.year = activity.year;
view raw 7.sql hosted with ❤ by GitHub

which returns the desired result below:

name score activity year
Zamani C football 2020
Zamani B bicycling 2019
Ayo A dancing 2020
view raw 8.md hosted with ❤ by GitHub

The thought of how multiple inner joins work can be confusing right? Well, what actually happens like in 7.sql above is that every single join produces a single derived table which is then joined to the next table and on and on. Using the 7.sql example above:
JOIN 1: This is the inner join between the person table and the grade tables. Let’s call this result derived table one (DT1)
JOIN 2: This is another inner join between DT1 and the activity table. The result gotten here is the final result returned by this query

So having delivered what is needed in time, let us refactor what we have written for a healthy codebase. There are several ways the query in 7.sql could have been written. For example:

SELECT name, score, activity, a.year
FROM person AS p
INNER JOIN grade AS g
ON p.id = g.person_id
INNER JOIN activity AS a
ON p.id = a.person_id
AND g.year = a.year;
view raw 9.sql hosted with ❤ by GitHub

The AS keyword is used for creating an alias - an alias is a temporary name that only exists for the duration of the query. Good use cases for aliases are when:

  • You want to make column names or table names more readable
  • You want to write less because the names are long. - Example: there is more than one table in your query - so you write p.id = a.person_id instead of person.id = activity.person_id.

If the key field in grade and activity tables is also id (and not person_id), the SQL code would rather be:

SELECT name, score, activity, a.year
FROM person AS p
INNER JOIN grade AS g
USING(id)
INNER JOIN activity AS a
USING(id, year)
view raw 10.sql hosted with ❤ by GitHub

You have seen the ON clause so far but if the key field you are joining on has the same name in both tables, use the USING keyword instead.

So, I believe you are now becoming an SQL savant! Oh Gosh! This new Javascript teacher is so demanding! Now, he is asking for all students' academic details regardless of whether they have a grade or not. Well! Body no be wood! 😁 So, we have to push this request to another sprint right? 😉 We would set up a meeting with him in the near future to talk about how he wants this because this sounds like a job for the OUTER JOINS and there are 3 kinds.

Stay tuned to this series for my next article on OUTER JOINS! Have an amazing and fulfilled week ahead!

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (4)

Collapse
 
ijsucceed profile image
Jeremy Ikwuje • Edited

I could hear your voice in this write-up 👏.

Thank you for mentioning the USING keyword. It's clean, compare to p.id = g.id.

Having encountered 6.md several times, what I do is to use PHP logic to remove duplicated results 😏. But it becomes difficult with several multiple JOIN.

Never knew one could just append the AND keyword without HEADACHE 😃 😃.

Seems I becoming an SQL savant! 💪

Collapse
 
joyadauche profile image
Joy Ada Uche • Edited

Thanks, @ijsucceed . I'm glad you are becoming an SQL Savant! 😃

Collapse
 
geraldchioke profile image
Chioke Gerald Ikenna

Body no be wood...lol. Great post Joy. Looking forward to the next article on OUTER JOINS.

Collapse
 
joyadauche profile image
Joy Ada Uche

Haha, Sure! Thanks a lot @geraldchioke

Billboard image

Try REST API Generation for Snowflake

DevOps for Private APIs. Automate the building, securing, and documenting of internal/private REST APIs with built-in enterprise security on bare-metal, VMs, or containers.

  • Auto-generated live APIs mapped from Snowflake database schema
  • Interactive Swagger API documentation
  • Scripting engine to customize your API
  • Built-in role-based access control

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay