-- Customers & Orders
Q1: Retrieve all customers who have placed an order.
A1:
SELECT DISTINCT c.*
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id;
Q2: List orders along with the customer names.
A2:
SELECT o.order_id, o.total_amount, o.order_date, c.name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;
Q3: Find customers who haven’t placed any orders.
A3:
SELECT c.*
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
WHERE o.order_id IS NULL;
-- Employees & Departments
Q1: Retrieve all employees and their department names, including those without a
department.
A1:
SELECT e.name AS employee_name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id;
Q2: Find departments that have no employees.
A2:
SELECT d.*
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
WHERE e.emp_id IS NULL;
-- Filtering with Aggregation & JOIN
Q1: Retrieve the average grade per course.
A1:
SELECT c.title, AVG(e.grade) AS avg_grade
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
GROUP BY c.title;
Q2: List students who are not enrolled in any courses.
A2:
SELECT s.*
FROM students s
LEFT JOIN enrollments e ON s.student_id = e.student_id
WHERE e.course_id IS NULL;
Q3: Find students who scored above the course average grade.
A3:
SELECT s.name, c.title, e.grade
FROM enrollments e
JOIN students s ON s.student_id = e.student_id
JOIN courses c ON c.course_id = e.course_id
WHERE e.grade > (
SELECT AVG(e2.grade)
FROM enrollments e2
WHERE e2.course_id = e.course_id
);
-- Medium Level (Complex JOINS & Aggregations)
Q1: Retrieve all employees with their department name and manager details.
A1:
SELECT e.name AS employee_name, d.dept_name, m.manager_name, m.bonus
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
LEFT JOIN managers m ON d.manager_id = m.manager_id;
Q2: Find departments that do not have a manager assigned.
A2:
SELECT *
FROM departments
WHERE manager_id IS NULL;
Q3: Retrieve employees who earn more than their department’s average salary.
A3:
SELECT e.*
FROM employees e
JOIN (
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
) dept_avg ON e.department_id = dept_avg.department_id
WHERE e.salary > dept_avg.avg_salary;
-- Product Sales Analysis with JOINS
Q1: Retrieve all products that have never been sold.
A1:
SELECT p.*
FROM products p
LEFT JOIN order_items oi ON p.product_id = oi.product_id
WHERE oi.order_id IS NULL;
Q2: Find the top 3 best-selling products based on total quantity sold.
A2:
SELECT p.product_name, SUM(oi.quantity) AS total_sold
FROM products p
JOIN order_items oi ON p.product_id = oi.product_id
GROUP BY p.product_name
ORDER BY total_sold DESC
LIMIT 3;
Q3: Get the total revenue per product category.
A3:
SELECT p.category, SUM(oi.quantity * oi.price) AS total_revenue
FROM products p
JOIN order_items oi ON p.product_id = oi.product_id
GROUP BY p.category;
-- Advanced Filtering with JOINS: Employee Performance
Q1: Retrieve all employees and the projects they are working on.
A1:
SELECT e.name, p.project_name, ep.role
FROM employees e
JOIN employee_projects ep ON e.emp_id = ep.emp_id
JOIN projects p ON ep.project_id = p.project_id;
Q2: Find employees who are not assigned to any project.
A2:
SELECT e.*
FROM employees e
LEFT JOIN employee_projects ep ON e.emp_id = ep.emp_id
WHERE ep.project_id IS NULL;
Q3: List projects that have no employees assigned.
A3:
SELECT p.*
FROM projects p
LEFT JOIN employee_projects ep ON p.project_id = ep.project_id
WHERE ep.emp_id IS NULL;
-- Customer Order Behavior Analysis
Q1: Find customers who have placed more than 5 orders.
A1:
SELECT c.*, COUNT(o.order_id) AS order_count
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.name, c.email
HAVING COUNT(o.order_id) > 5;
Q2: Retrieve the total amount spent per customer.
A2:
SELECT c.customer_id, c.name, SUM(o.total_amount) AS total_spent
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.name;
Q3: Get customers who haven’t placed any orders in the last 6 months.
A3:
SELECT c.*
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id AND o.order_date > CURRENT_DATE
- INTERVAL '6 months'
GROUP BY c.customer_id, c.name, c.email
HAVING COUNT(o.order_id) = 0;
-- Mastering Aggregations with HAVING & JOINS
Q1: Find total revenue per region, but only for regions where revenue exceeds
$10,000.
A1:
SELECT region, SUM(quantity * price) AS total_revenue
FROM sales
GROUP BY region
HAVING SUM(quantity * price) > 10000;
Q2: Retrieve the lowest revenue-generating product.
A2:
SELECT product_name, SUM(quantity * price) AS total_revenue
FROM sales
GROUP BY product_name
ORDER BY total_revenue ASC
LIMIT 1;
Q3: Get the monthly revenue for the past 6 months.
A3:
SELECT DATE_TRUNC('month', sale_date) AS month,
SUM(quantity * price) AS revenue
FROM sales
WHERE sale_date >= CURRENT_DATE - INTERVAL '6 months'
GROUP BY month
ORDER BY month;
-- Hard Level (Advanced JOINS & Real-World Scenarios)
Q1: Retrieve all employees with their department names and managers.
A1:
SELECT e.name AS employee_name, d.dept_name, m.manager_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
LEFT JOIN managers m ON d.manager_id = m.manager_id;
Q2: Find employees who earn more than their department’s average salary.
A2:
SELECT e.*
FROM employees e
JOIN (
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
) dept_avg ON e.department_id = dept_avg.department_id
WHERE e.salary > dept_avg.avg_salary;
Q3: Calculate the total salary expense per manager, including bonus amounts.
A3:
SELECT m.manager_name, SUM(e.salary) + m.bonus AS total_expense
FROM managers m
JOIN departments d ON m.manager_id = d.manager_id
JOIN employees e ON d.department_id = e.department_id
GROUP BY m.manager_name, m.bonus;
-- Complex Many-to-Many Relationship: Student-Course Enrollments
Q1: Retrieve all students along with their enrolled courses.
A1:
SELECT s.name AS student_name, c.title AS course_title
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id;
Q2: Find students who are enrolled in more than 3 courses.
A2:
SELECT s.name, COUNT(e.course_id) AS course_count
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
GROUP BY s.name
HAVING COUNT(e.course_id) > 3;
Q3: Get the highest and lowest grades for each course.
A3:
SELECT c.title,
MAX(e.grade) AS highest_grade,
MIN(e.grade) AS lowest_grade
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
GROUP BY c.title;
-- E-commerce Data Analysis with JOINS & Aggregation
Q1: Find the total revenue per customer, including product details.
A1:
SELECT c.name, p.product_name, SUM(oi.quantity * oi.price) AS total_spent
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
GROUP BY c.name, p.product_name;
Q2: Retrieve the top 5 customers based on total spending.
A2:
SELECT c.name, SUM(o.total_amount) AS total_spent
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.name
ORDER BY total_spent DESC
LIMIT 5;
Q3: Get the most profitable product category.
A3:
SELECT p.category, SUM(oi.quantity * oi.price) AS total_revenue
FROM products p
JOIN order_items oi ON p.product_id = oi.product_id
GROUP BY p.category
ORDER BY total_revenue DESC
LIMIT 1;
Q4: Find customers who purchased products from at least 3 different categories.
A4:
SELECT c.name, COUNT(DISTINCT p.category) AS category_count
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
GROUP BY c.name
HAVING COUNT(DISTINCT p.category) >= 3;