Nested Select Statements in MySQL for Enhanced Query

Victor A. Oguntuase Feb 09, 2022
  1. Use the Inner-Outer Query Method to Implement the Nested SELECT Statement in MySQL
  2. Implement the Nested SELECT Statement as an Alternative to JOINS in MySQL
Nested Select Statements in MySQL for Enhanced Query

The SELECT statement is the primary function for retrieving data from a database using SQL. However, there are use-cases where the results of an executed SELECT operation need to be manipulated or retrieved.

The nested SELECT statement approach offers a convenient solution for such advanced queries.

Similar to general programming languages, SQL offers multiple ways of achieving the same results. Nested SELECT statements can serve as an alternative to JOINS.

However, there are cases where using nested SELECT statements is the optimal choice. This tutorial explores these concepts and use-cases in a few practical examples.

Use the Inner-Outer Query Method to Implement the Nested SELECT Statement in MySQL

The inner-outer query method in MySQL is similar in operation to a nested expression or function in most general programming languages. The inner query executes first then its result is passed to a wrapping outer query, typically via a WHERE clause.

For example, let’s create a sample table Employee with an id, name, title, and salary column.

-- Initializing and selecting a database
CREATE DATABASE test_company;
USE test_company;

-- creating a sample employees table
CREATE TABLE employees(
    id INT AUTO_INCREMENT,
    name VARCHAR (255),
    title VARCHAR(255),
    salary INT,

    PRIMARY KEY (id)
);

-- populating the employees' table with information
INSERT INTO employees (name, title, salary) Values
('James Maddison','Computer Engineer',80000),
('Matthew Defoe','Software Architect',150000),
('Daniel Jameson','Software Engineer II', 95000),
('Jules Reddington','Senior Software Engineer',120000),
('Carlos Rodriguez','Data Engineer',100000);

-- previewing the employees' table
SELECT * FROM employees;

Output:

id	name				title						salary
1	James Maddison		Computer Engineer			80000
2	Matthew Defoe		Software Architect			150000
3	Daniel Jameson		Software Engineer II		95000
4	Jules Reddington	Senior Software Engineer	120000
5	Carlos Rodriguez	Data Engineer				100000
-----------------------------------------------------------------------------------------
1 row(s) affected
0 row(s) affected
0 row(s) affected
5 row(s) affected Records: 5  Duplicates: 0  Warnings: 0
5 row(s) returned

To find the details of Employees that currently earn more than the average salary in the company.

We first calculate the average salary in the company using the AVG() function, then we filter the Employees table based on the returned average value.

Typically, the more computational query is the inner query for improved efficiency and logic. This approach ensures the outer sub-query only filters a significantly reduced table of values.

More details on choosing an appropriate inner and outer sub-query are available via this reference from w3resource.

/* Inner query
SELECT AVG(salary) FROM employees;

Outer query
SELECT * FROM employees
WHERE salary > (Inner query)
*/

-- Full Query
SELECT * FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees)
ORDER BY salary DESC;   -- starting from the highest-paid

Output:

id	name				title						salary
2	Matthew Defoe		Software Architect			150000
4	Jules Reddington	Senior Software Engineer	120000
-----------------------------------------------------------------------------------------
0.032 sec / 0.000 sec
2 row(s) returned

The query returns two employees who currently earn above the average salary, i.e., $109,000.

Implement the Nested SELECT Statement as an Alternative to JOINS in MySQL

As a replacement for implementing JOINS when retrieving data from more than one table, nested SELECT can be a good alternative.

Add another table named Projects related to the Employees table via a foreign key. Also, let’s add the extra required column and foreign key constraint to the Employees table.

-- Adding a new projects table
CREATE TABLE projects(
	project_id INT,
    project_name VARCHAR(255) DEFAULT NULL,
    programming_language VARCHAR(255) DEFAULT 'N/A',

    PRIMARY KEY (project_id)
);

-- This modifies the employees' table and adds a foreign key
ALTER TABLE employees
ADD project_id INT,
ADD FOREIGN KEY (project_id) REFERENCES projects(project_id);

-- Populating the projects table and updating the employees' table with project_ids
INSERT INTO projects(project_id, project_name, programming_language) VALUES
(100, 'Movie Recommendation System', 'Python, Javascript, R'),
(105, 'Deep Learning Data Pipeline 10', 'Python, R, SQL'),
(107, 'Web-Based Diagnostic Support AI System', 'Python, Javascript, Html, CSS');

INSERT INTO projects(project_id, project_name) VALUES
(311, 'Computer Hardware Revamp'),
(109, 'Implementing an Advanced Conversational Agent for Effex.inc');

SELECT * FROM projects;

Output:

project_id	project_name							programming_language
100			Movie Recommendation System				Python, Javascript, R
105			Deep Learning Data Pipeline 10			Python, R, SQL
107			Web-Based Diagnostic Support AI System	Python, Javascript, Html, CSS
109			Implementing an Advanced Conversational N/A
			Agent for Effex.inc
311			Computer Hardware Revamp				N/A
-----------------------------------------------------------------------------------------
0 row(s) affected
5 row(s) affected Records: 5  Duplicates: 0  Warnings: 0
5 row(s) affected Records: 5  Duplicates: 0  Warnings: 0
5 row(s) returned

Now, update the project_id column in the employees table.

-- NOW relating employees to projects
UPDATE employees
SET project_id = 311
WHERE id = 1;

UPDATE employees
SET project_id = 109
WHERE id = 2;

UPDATE employees
SET project_id = 100
WHERE id = 3;

UPDATE employees
SET project_id = 107
WHERE id = 4;

UPDATE employees
SET project_id = 105
WHERE id = 5;

SELECT * FROM employees;

Output:

id	name			 title					  salary	project_id
1	James Maddison	 Computer Engineer		  80000		311
2	Matthew Defoe	 Software Architect	  	  150000	109
3	Daniel Jameson	 Software Engineer II	  95000		100
4	Jules Reddington Senior Software Engineer 120000	107
5	Carlos Rodriguez Data Engineer			  100000	105

-----------------------------------------------------------------------------------------
1 row(s) affected Rows matched: 1  Changed: 1  Warnings: 0
1 row(s) affected Rows matched: 1  Changed: 1  Warnings: 0
1 row(s) affected Rows matched: 1  Changed: 1  Warnings: 0
1 row(s) affected Rows matched: 1  Changed: 1  Warnings: 0
1 row(s) affected Rows matched: 1  Changed: 1  Warnings: 0
5 row(s) returned

We can then select values from both tables using a nested SELECT statement. Let us find the name, title, salary, project name, and programming languages of employees that use JavaScript for their job.

First, the inner query gets values from the projects table. Then, the outer query fetches relevant data from the Result-Set for generating the needed view.

-- Selecting details of employees that use Javascript (Inner Query)
SELECT project_id, project_name FROM projects WHERE programming_language LIKE '%Javascript%';

Output:

project_id	project_name
100			Movie Recommendation System
107			Web-Based Diagnostic Support AI System
-----------------------------------------------------------------------------------------
2 row(s) returned

Now, the full query.

/*
-- Inner query
SELECT project_id, project_name, programming_language FROM projects WHERE programming_language LIKE '%Javascript%';

-- Outer query
SELECT E.name AS 'Employee Name', E.title AS 'Job Title', E.Salary AS 'Salary',
P.project_name AS 'Current Project', P.programming_language AS 'Programming Language'
FROM employees AS E,
(Inner query) AS P
WHERE E.project_id = P.project_id;
*/

-- Full query
SELECT E.name AS 'Employee Name', E.title AS 'Job Title', E.Salary AS 'Salary',
P.project_name AS 'Current Project'
FROM employees AS E,
(SELECT project_id, project_name FROM projects WHERE programming_language LIKE '%Javascript%') AS P
WHERE E.project_id = P.project_id;

Output:

Employee Name		Job Title					Salary	Current Project
Daniel Jameson	 	Software Engineer II		95000	Movie Recommendation System
Jules Reddington	Senior Software Engineer	120000	Web-Based Diagnostic Support AI 														System
-----------------------------------------------------------------------------------------
2 row(s) returned

This result is also achievable with a well-written JOIN statement. However, there is a choice of a trade-off between efficiency and convenience.

Victor A. Oguntuase avatar Victor A. Oguntuase avatar

Victor is an experienced Python Developer, Machine Learning Engineer and Technical Writer with interests across various fields of science and engineering. He is passionate about learning new technologies and skill and working on challenging problems. He enjoys teaching, intellectual discourse, and gaming, among other things.

LinkedIn GitHub

Related Article - MySQL Select

Related Article - MySQL Query