Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Mastering SQL Joins 1684493647

Download as pdf or txt
Download as pdf or txt
You are on page 1of 17

Mastering SQL Joins: A Comprehensive Guide to Querying Relational

Databases

SQL is a powerful language for working with relational databases. One of the key features of SQL is the
ability to join tables together, allowing you to combine data from multiple sources into a single result
set. However, many SQL users find joins to be complex and confusing, and struggle to use them
effectively.

This book aims to demystify SQL joins and provide a comprehensive guide to querying relational
databases. Whether you're a beginner who is just starting to learn SQL, or an experienced developer
who wants to deepen your understanding of joins, this book has something for you.

We'll start by introducing the basic concepts of SQL joins, including the different types of joins and how
they work. We'll then move on to more advanced topics, such as using aggregate functions with joins,
optimizing join performance, and dealing with null values.

Throughout the book, we'll use examples and exercises to help you practice your SQL skills and build
your understanding of joins. We'll also provide tips and best practices for writing efficient and effective
SQL code.
By the end of this book, you'll be able to confidently use SQL joins to query relational databases and
solve complex data problems. Whether you're working with small datasets or large enterprise
systems, the techniques and strategies in this book will help you get the most out of your SQL
queries.
1. Inner Join:

An inner join returns only the rows that have matching values in both tables being joined. It includes
only the common values in both tables.

Example:

Consider two tables, 'students' and 'exams'. We want to query the student name and exam name for
all students who have taken an exam.

SELECT students.name, exams.exam_name

FROM students

INNER JOIN exams

ON students.student_id = exams.student_id;

This query will return only the rows where both the 'students' and 'exams' tables have matching
values in the 'student_id' column.

2. Left Join:

A left join returns all the rows from the left table, and the matching rows from the right table. If there
is no matching row in the right table, NULL values are returned.

Example:

Consider two tables, 'employees' and 'departments'. We want to query the name and department
name for all employees, even if they do not belong to a department.

SELECT employees.name, departments.department_name

FROM employees

LEFT JOIN departments

ON employees.department_id = departments.department_id;

This query will return all the rows from the 'employees' table and only the matching rows from the
'departments' table. If an employee does not belong to a department, the department name will be
NULL.
3. Right Join:

A right join returns allthe rows from the right table, and the matching rows from the left table. If
there is no matching row in the left table, NULL values are returned.

Example:

Consider the same two tables as above, 'employees' and 'departments'. We want to query the name
and department name for all departments, even if they do not have any employees.

SELECT employees.name, departments.department_name

FROM employees

RIGHT JOIN departments

ON employees.department_id = departments.department_id;

This query will return all the rows from the 'departments' table and only the matching rows from the
'employees' table. If a department does not have any employees, the employee name will be NULL.

4. Full Outer Join:

A full outer join returns all the rows from both tables, including the non-matching rows. If there is no
matching row in one table, NULL values are returned.

Example:

Consider two tables, 'students' and 'courses'. We want to query the student name and course name
for all students and courses, including those who do not have any courses or those without any
students.

SELECT students.name, courses.course_name

FROM students

FULL OUTER JOIN courses

ON students.student_id = courses.student_id;

This query will return all the rows from both the 'students' and 'courses' tables, including those with
non-matching values. If a student does not have any courses or a course does not have any students,
the corresponding name will be NULL.
Now that we've coveredthe four main types of joins in SQL, here are 25 exercises about joins with
solutions and explanations:

1. Write a SQL query to display the first name, last name, and department name of all employees.

Solution:

SELECT employees.first_name, employees.last_name, departments.department_name

FROM employees

INNER JOIN departments

ON employees.department_id = departments.department_id;

Explanation:

This query uses an inner join to combine the 'employees' and 'departments' tables on the
'department_id' column. It selects the 'first_name', 'last_name', and 'department_name' columns
from the resulting table.

2. Write a SQL query to display the first name, last name, and department name of all employees,
including those who do not belong to a department.

Solution:

SELECT employees.first_name, employees.last_name, departments.department_name

FROM employees

LEFT JOIN departments

ON employees.department_id = departments.department_id;

Explanation:

This query uses a left join to combine the 'employees' and 'departments' tables on the
'department_id' column. It selects the 'first_name', 'last_name', and 'department_name' columns
from the resulting table. If an employee does not belong to a department, the department name will
be NULL.

3. Write a SQL query to display the first name, last name, and department name of all employees,
including those whose department does not have a name.
Solution:

SELECT employees.first_name, employees.last_name, departments.department_name

FROMemployees

LEFT JOIN departments

ON employees.department_id = departments.department_id OR departments.department_id IS


NULL;

Explanation:

This query uses a left join to combine the 'employees' and 'departments' tables on the
'department_id' column. It selects the 'first_name', 'last_name', and 'department_name' columns
from the resulting table. If an employee belongs to a department that does not have a name, the
department name will be NULL.

4. Write a SQL query to display the first name, last name, and salary of all employees, as well as the
department name for those who belong to a department.

Solution:

SELECT employees.first_name, employees.last_name, employees.salary,


departments.department_name

FROM employees

LEFT JOIN departments

ON employees.department_id = departments.department_id;

Explanation:

This query uses a left join to combine the 'employees' and 'departments' tables on the
'department_id' column. It selects the 'first_name', 'last_name', 'salary', and 'department_name'
columns from the resulting table. If an employee does not belong to a department, the department
name will be NULL.

5. Write a SQL query to display the first name, last name, and title of all employees, as well as the
department name for those who belong to a department, and the manager name for those who have
a manager.

Solution:
SELECT e.first_name, e.last_name, e.title, d.department_name, m.first_name AS
manager_first_name, m.last_name AS manager_last_name

FROM employees e

LEFT JOIN departments d

ON e.department_id = d.department_id

LEFT JOIN employees m

ON e.manager_id = m.employee_id;

Explanation:

This query uses two left joins to combine the 'employees' and 'departments' tables on the
'department_id' column, and the 'employees' table with itself on the 'manager_id' column. It selects
the 'first_name', 'last_name', 'title', 'department_name', 'manager_first_name', and
'manager_last_name' columns from the resulting table. If an employee does not belong to a
department or does not have a manager, the corresponding values will be NULL.

Sure! Here are some more SQL exercises about joins:

6. Write a SQL query to display the first name, last name, and email of all employees, as well as the
name of their department and the name of their manager.

Solution:

SELECT e.first_name, e.last_name, e.email, d.department_name, m.first_name AS


manager_first_name, m.last_name AS manager_last_name

FROM employees e

LEFT JOIN departments d

ON e.department_id = d.department_id

LEFT JOIN employees m

ON e.manager_id = m.employee_id;

Explanation:

This query uses two left joins to combine the 'employees' and 'departments' tables on the
'department_id' column, and the 'employees' table with itself on the 'manager_id' column. It selects
the 'first_name', 'last_name', 'email', 'department_name', 'manager_first_name', and
'manager_last_name' columns from the resulting table. If an employee does not belong to a
department or does not have a manager, the corresponding values will be NULL.
7. Write a SQL query to display the name and price of all products, as well as the name of their
category.

Solution:

SELECT p.product_name, p.price, c.category_name

FROM products p

INNER JOIN categories c

ON p.category_id = c.category_id;

Explanation:

This query uses an inner join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selectsthe 'product_name', 'price', and 'category_name' columns from the resulting table.
It will return only the rows where both tables have matching values.

8. Write a SQL query to display the name and price of all products, as well as the name of their
category, even for products that do not have a category.

Solution:

SELECT p.product_name, p.price, c.category_name

FROM products p

LEFT JOIN categories c

ON p.category_id = c.category_id;

Explanation:

This query uses a left join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selects the 'product_name', 'price', and 'category_name' columns from the resulting table.
If a product does not have a category, the category name will be NULL.

9. Write a SQL query to display the name and price of all products, as well as the name of their
category, even for categories that do not have any products.

Solution:

SELECT p.product_name, p.price, c.category_name


FROM products p

RIGHT JOIN categories c

ON p.category_id = c.category_id;

Explanation:

This query uses a right join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selects the 'product_name', 'price', and 'category_name' columns from the resulting table.
If a category does not have any products, the product name and price will be NULL.

10. Write aSQL query to display the name and price of all products, as well as the name of their
category, including categories that do not have any products and products that do not have a
category.

Solution:

SELECT p.product_name, p.price, c.category_name

FROM products p

FULL OUTER JOIN categories c

ON p.category_id = c.category_id;

Explanation:

This query uses a full outer join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selects the 'product_name', 'price', and 'category_name' columns from the resulting table.
If a category does not have any products or a product does not have a category, the corresponding
values will be NULL.

11. Write a SQL query to display the name and price of all products that have a price greater than
$10.

Solution:

SELECT product_name, price

FROM products

WHERE price > 10;

Explanation:
This query selects the 'product_name' and 'price' columns from the 'products' table, but only returns
the rows where the 'price' column is greater than 10.

12. Write a SQL query to display the name and price of all products that have a price greater than $10
and belong to the 'Electronics' category.

Solution:

SELECT p.product_name, p.price

FROM products p

INNER JOIN categories c

ON p.category_id = c.category_id

WHERE p.price > 10 AND c.category_name = 'Electronics';

Explanation:

This query uses an inner join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selects the 'product_name' and 'price' columns from the resulting table, but only returns
the rows where the 'price' column is greater than 10 and the 'category_name' column is 'Electronics'.

Sure, here are some more SQL exercises about joins:

13. Write a SQL query to display the name and price of all products that have a price greater than $10
or belong to the 'Electronics' category.

Solution:

SELECT p.product_name, p.price

FROM products p

LEFT JOIN categories c

ON p.category_id = c.category_id

WHERE p.price > 10 OR c.category_name = 'Electronics';

Explanation:

This query uses a left join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selects the 'product_name' and 'price' columns from the resulting table, but only returns
the rows where the 'price' column is greater than 10 or the 'category_name' column is 'Electronics'. If
a product does not have a category, the category name will be NULL but the row will still be included
in the result set.

14. Write a SQL query to display the name and price of all products that do not belong to the
'Electronics' category.

Solution:

SELECT p.product_name, p.price

FROM products p

LEFT JOIN categories c

ON p.category_id = c.category_id

WHERE c.category_name IS NULL OR c.category_name != 'Electronics';

Explanation:

This query uses a left join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selects the 'product_name' and 'price' columns from the resulting table,but only returns
the rows where the category name is NULL (indicating that the product does not belong to a
category) or the category name is not 'Electronics'. This query ensures that all products that do not
belong to the 'Electronics' category are included in the result set.

15. Write a SQL query to display the name and price of all products that belong to the 'Electronics'
category and were added in the last 30 days.

Solution:

SELECT p.product_name, p.price

FROM products p

INNER JOIN categories c

ON p.category_id = c.category_id

WHERE c.category_name = 'Electronics' AND p.added_date >= DATEADD(day, -30, GETDATE());

Explanation:

This query uses an inner join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selects the 'product_name' and 'price' columns from the resulting table, but only returns
the rows where the 'category_name' column is 'Electronics' and the 'added_date' column is within
the last 30 days. The DATEADD() function is used to subtract 30 days from the current date
(GETDATE()).

16. Write a SQL query to display the name and price of all products that were added in the last 30
days, sorted by price in descending order.

Solution:

SELECT product_name, price

FROM products

WHERE added_date >= DATEADD(day, -30, GETDATE())

ORDERBY price DESC;

Explanation:

This query selects the 'product_name' and 'price' columns from the 'products' table, but only returns
the rows where the 'added_date' column is within the last 30 days. The DATEADD() function is used
to subtract 30 days from the current date (GETDATE()). The results are then sorted by price in
descending order using the ORDER BY clause with the DESC keyword.

17. Write a SQL query to display the name and price of the three most expensive products.

Solution:

SELECT TOP 3 product_name, price

FROM products

ORDER BY price DESC;

Explanation:

This query selects the 'product_name' and 'price' columns from the 'products' table, and returns only
the top 3 rows sorted by price in descending order using the TOP and ORDER BY clauses.

18. Write a SQL query to display the name and price of the cheapest product in each category.

Solution:

SELECT p.product_name, p.price, c.category_name


FROM products p

INNER JOIN categories c

ON p.category_id = c.category_id

WHERE p.price = (SELECT MIN(price) FROM products WHERE category_id = p.category_id);

Explanation:

This query uses an inner join to combine the 'products' and 'categories' tables on the 'category_id'
column. It selects the 'product_name', 'price', and 'category_name' columns from the resulting table,
but only returns the rows where the 'price' column is theminimum price for each category. This is
achieved by using a subquery in the WHERE clause to find the minimum price for each category, and
then comparing it to the 'price' column of the 'products' table. The subquery is filtered by the
'category_id' column of the 'products' table to ensure that only the minimum price for each category
is returned.

Sure, here are some more SQL exercises about joins:

19. Write a SQL query to display the name and price of all products that were ordered by at least one
customer, along with the number of times each product was ordered.

Solution:

SELECT p.product_name, p.price, COUNT(o.product_id) AS order_count

FROM products p

LEFT JOIN order_items o

ON p.product_id = o.product_id

GROUP BY p.product_name, p.price

HAVING COUNT(o.product_id) > 0;

Explanation:

This query uses a left join to combine the 'products' and 'order_items' tables on the 'product_id'
column. It selects the 'product_name' and 'price' columns from the 'products' table, and also counts
the number of times each product was ordered using the COUNT() function and the 'product_id'
column of the 'order_items' table. The results are grouped by 'product_name' and 'price' using the
GROUP BY clause. The HAVING clause is used to filter out products that were not ordered by any
customers.

20. Write a SQL query to display the name and email of all customers who have not placed any
orders.
Solution:

SELECT c.customer_name, c.email

FROM customers c

LEFT JOIN orders o

ON c.customer_id = o.customer_id

WHERE o.order_id IS NULL;

Explanation:

This query uses a left join to combine the 'customers' and 'orders' tables on the 'customer_id'
column. It selects the 'customer_name' and 'email' columns from the 'customers' table, but only
returns the rows where the 'order_id' column of the 'orders' table is NULL. This ensures that only
customers who have not placed any orders are included in the result set.

21. Write a SQL query to display the name and total price of all orders, grouped by customer.

Solution:

SELECT c.customer_name, SUM(oi.price * oi.quantity) AS total_price

FROM customers c

LEFT JOIN orders o

ON c.customer_id = o.customer_id

LEFT JOIN order_items oi

ON o.order_id = oi.order_id

GROUP BY c.customer_name;

Explanation:

This query uses two left joins to combine the 'customers', 'orders', and 'order_items' tables on their
respective keys. It selects the 'customer_name' column from the 'customers' table, and calculates the
total price of each order by multiplying the 'price' and 'quantity' columns of the 'order_items' table,
and summing the results using the SUM() function. The results are grouped by 'customer_name'
using the GROUP BY clause.

22. Write a SQL query to display the name and total price of all orders that were placed in the last
month, grouped by customer.
Solution:

SELECT c.customer_name, SUM(oi.price * oi.quantity) AS total_price

FROM customers c

INNER JOIN orders o

ON c.customer_id = o.customer_idINNER JOIN order_items oi

ON o.order_id = oi.order_id

WHERE o.order_date >= DATEADD(month, -1, GETDATE())

GROUP BY c.customer_name;

Explanation:

This query uses two inner joins to combine the 'customers', 'orders', and 'order_items' tables on their
respective keys. It selects the 'customer_name' column from the 'customers' table, and calculates the
total price of each order by multiplying the 'price' and 'quantity' columns of the 'order_items' table,
and summing the results using the SUM() function. The results are grouped by 'customer_name'
using the GROUP BY clause. The WHERE clause is used to filter only the orders that were placed in the
last month, by subtracting one month from the current date (GETDATE()) using the DATEADD()
function.

Sure, here are some more SQL exercises about joins:

23. Write a SQL query to display the name and total price of all orders that were placed by customers
who live in the same city as the store.

Solution:

SELECT c.customer_name, SUM(oi.price * oi.quantity) AS total_price

FROM customers c

INNER JOIN orders o

ON c.customer_id = o.customer_id

INNER JOIN order_items oi

ON o.order_id = oi.order_id

WHERE c.city = (SELECT city FROM stores WHERE store_id = 1)

GROUP BY c.customer_name;

Explanation:
This query uses two inner joins to combine the 'customers', 'orders', and 'order_items' tables on their
respective keys. It selects the 'customer_name' column from the 'customers' table, and calculates the
total price of each order by multiplying the 'price' and 'quantity' columns of the 'order_items' table,
and summing the results using the SUM() function. The results are grouped by 'customer_name'
using the GROUP BY clause. The WHERE clause is used to filter only the orders that were placed by
customers who live in the same city as the store with ID 1, which is selected using a subquery.

24. Write a SQL query to display the name and total price of all orders that were placed by customers
who have placed at least two orders.

Solution:

SELECT c.customer_name, SUM(oi.price * oi.quantity) AS total_price

FROM customers cINNER JOIN orders o

ON c.customer_id = o.customer_id

INNER JOIN order_items oi

ON o.order_id = oi.order_id

WHERE c.customer_id IN (SELECT customer_id FROM orders GROUP BY customer_id HAVING


COUNT(*) >= 2)

GROUP BY c.customer_name;

Explanation:

This query uses two inner joins to combine the 'customers', 'orders', and 'order_items' tables on their
respective keys. It selects the 'customer_name' column from the 'customers' table, and calculates the
total price of each order by multiplying the 'price' and 'quantity' columns of the 'order_items' table,
and summing the results using the SUM() function. The results are grouped by 'customer_name'
using the GROUP BY clause. The WHERE clause is used to filter only the orders that were placed by
customers who have placed at least two orders, by selecting the 'customer_id' column from the
'orders' table, grouping by it using the GROUP BY clause, and filtering the results using the HAVING
clause.

25. Write a SQL query to display the name and total price of all orders that were placed by customers
who have never returned any products.

Solution:

SELECT c.customer_name, SUM(oi.price * oi.quantity) AS total_price

FROM customers c
INNER JOIN orders o

ON c.customer_id = o.customer_id

INNER JOIN order_items oi

ON o.order_id = oi.order_id

WHERE c.customer_id NOT IN (SELECT customer_id FROM returns)

GROUP BY c.customer_name;

Explanation:

This query uses two inner joins to combine the 'customers', 'orders', and 'order_items' tables on their
respective keys. It selects the 'customer_name' column from the 'customers' table, and calculates the
total price of each order by multiplying the 'price' and 'quantity' columns of the 'order_items' table,
and summing the results using the SUM() function. The results are grouped by 'customer_name'
using the GROUP BY clause. The WHERE clause is used to filter only the orders that were placed by
customers who have never returned any products, by selecting the 'customer_id' column from the
'returns' table and using the NOT IN operator to exclude those customers from the result set.

You might also like