Subqueries in SQL are powerful tools that analytics engineers leverage to perform advanced data retrieval and computation directly within SELECT and FROM clauses. By embedding queries within queries, subqueries allow for complex analyses such as calculating averages, counting records dynamically, and filtering based on aggregated data.
In this tutorial, “SQL Exercises: Subqueries In SELECT And FROM,” you’ll learn how to effectively implement subqueries to enrich your data results, compare individual records against aggregated metrics, and create inline views for efficient querying. Mastering subqueries enhances your ability to produce precise, context-rich insights crucial for informed decision-making and robust data analysis.
🚀 Jump Right to Exercise Tasks: SQL Exercises – Subqueries In SELECT And FROM
Understanding Subqueries in SELECT
Imagine you’re evaluating employee salaries relative to their department averages. Using a subquery in the SELECT clause, you can compare each employee’s salary directly to the department average, highlighting high-performing employees easily.
Practical Example
SELECT employee_name,
salary,
(SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = e1.department_id) AS dept_avg_salary
FROM employees e1;
Example Solution Explained:
This query lists each employee’s salary alongside their department’s average salary, calculated through a subquery. This helps quickly identify those earning above or below average.
Example Output:
employee_name | salary | dept_avg_salary
--------------|--------|----------------
Alice Jones | 75000 | 68000
Bob Smith | 60000 | 68000
Key Takeaways:
- Subqueries within SELECT enrich main query results.
- Useful for dynamic computations per row.
Inline Views Using Subqueries in FROM
Suppose you’re tasked with analyzing recent sales performance. You can create an inline view using a subquery in the FROM clause, focusing only on orders from the last month to streamline your analysis.
Practical Example
SELECT recent_orders.order_id, recent_orders.order_total
FROM (SELECT order_id, order_total FROM orders WHERE order_date > '2022-03-01') AS recent_orders;
Example Solution Explained:
This query creates an inline table (recent_orders) of recent orders and then selects from this focused dataset, improving query efficiency and clarity.
Example Output:
order_id | order_total
---------|------------
1001 | 350.00
1002 | 150.00
Key Takeaways:
- Inline views simplify complex queries.
- Enhance performance by pre-filtering data.
Counting and Aggregating with Subqueries
Let’s say you want to identify product categories by their popularity. A subquery can count products within each category dynamically, giving immediate insight into category performance.
Practical Example
SELECT category_name,
(SELECT COUNT(*) FROM products WHERE products.category_id = categories.category_id) AS product_count
FROM categories;
Example Solution Explained:
This subquery calculates the number of products within each category, clearly displaying each category’s market presence.
Example Output:
category_name | product_count
--------------|--------------
Electronics | 15
Furniture | 8
Key Takeaways:
- Subqueries enable dynamic aggregation per group.
- Valuable for immediate, insightful summaries.
What You’ll Gain from Completing This Exercise
Mastering subqueries within SELECT and FROM clauses significantly enhances your analytical precision, allowing for sophisticated data comparisons, aggregations, and dynamic calculations crucial for detailed analytics.
Earn XP, Unlock Rewards, and Track Progress!
Log in to earn XP, unlock exciting rewards, and automatically track your progress as you master SQL subqueries and advanced analytics techniques!
Schema Information
Column Name | Data Type | Description |
---|---|---|
customer_id | INTEGER | Unique identifier for each customer |
first_name | TEXT | Customer's first name |
last_name | TEXT | Customer's last name |
TEXT | Customer's email address | |
city | TEXT | City of residence |
join_date | DATE | Date the customer joined |
phone | TEXT | Customer's phone number |
Column Name | Data Type | Description |
---|---|---|
city_id | INTEGER | Unique identifier for each city |
city_name | TEXT | Name of the city |
state | TEXT | State where the city is located |
Column Name | Data Type | Description |
---|---|---|
order_id | INTEGER | Unique identifier for each order |
customer_id | INTEGER | ID of the customer who placed the order |
employee_id | INTEGER | ID of the employee who handled the order |
order_date | DATE | Date when the order was placed |
status | TEXT | Order status (e.g., Shipped, Cancelled, Pending) |
total_amount | REAL | Total amount for the order |
Column Name | Data Type | Description |
---|---|---|
order_id | INTEGER | Associated order identifier |
product_id | INTEGER | Identifier for the product |
quantity | INTEGER | Quantity of the product in the order |
unit_price | REAL | Price per unit of the product |
Column Name | Data Type | Description |
---|---|---|
product_id | INTEGER | Unique identifier for each product |
product_name | TEXT | Name of the product |
category_id | INTEGER | Category to which the product belongs |
unit_price | REAL | Price per unit of the product |
stock_quantity | INTEGER | Quantity of items available in stock |
creation_date | DATE | Date the product was added to the system |
Column Name | Data Type | Description |
---|---|---|
supplier_id | INTEGER | Unique identifier for each supplier |
supplier_name | TEXT | Name of the supplier |
city | TEXT | City where the supplier is located |
products_supplied | TEXT | List of product IDs supplied (e.g., [90,91,33,121]) |
Column Name | Data Type | Description |
---|---|---|
movement_id | INTEGER | Unique identifier for each movement record |
product_id | INTEGER | Product being moved |
change_quantity | INTEGER | Change in quantity (+/-) |
movement_date | DATE | Date of the inventory movement |
reason | TEXT | Explanation (Sale, Restock, Adjustment, etc.) |
Column Name | Data Type | Description |
---|---|---|
employee_id | INTEGER | Unique identifier for each employee |
first_name | TEXT | Employee's first name |
last_name | TEXT | Employee's last name |
department_id | INTEGER | Identifier of the department |
hire_date | DATE | Date the employee was hired |
salary | INTEGER | Employee's salary |
Column Name | Data Type | Description |
---|---|---|
department_id | INTEGER | Unique identifier for each department |
department_name | TEXT | Name of the department |
location | TEXT | Location of the department |
Column Name | Data Type | Description |
---|---|---|
shipping_id | INTEGER | Unique identifier for each shipping record |
order_id | INTEGER | Order to which the shipping address belongs |
address | TEXT | Street address for shipping |
city | TEXT | Shipping city |
state | TEXT | Shipping state |
postal_code | INTEGER | Shipping postal/ZIP code |
Column Name | Data Type | Description |
---|---|---|
category_id | INTEGER | Unique identifier for each category |
category_name | TEXT | Name of the category |