30-Day SQL Practice Plan
From Beginner to Interview-Ready
Daily problems • Concepts • Solutions
How to Use This Plan:
• Spend 30-60 minutes daily
• Solve problems BEFORE looking at solutions
• Practice on: LeetCode, HackerRank, StrataScratch, SQLZoo
• Week 1: Basics → Week 2: Intermediate → Week 3: Advanced → Week 4: Interview Prep
Week Focus Difficulty
Week 1 (Day 1-7) SELECT, WHERE, ORDER BY, Basic Functions ■ Easy
Week 2 (Day 8-14) JOINs, GROUP BY, HAVING, Subqueries ■ Medium
Week 3 (Day 15-21) Window Functions, CTEs, Advanced Queries ■ Medium-Hard
Week 4 (Day 22-30) Interview Problems, Real Scenarios ■ Hard
WEEK 1: SQL Fundamentals
Focus: SELECT, WHERE, ORDER BY, Basic Functions
■ DAY 1: SELECT Basics
Concepts: SELECT, FROM, * (all columns), specific columns
Problem 1: Retrieve all columns from employees table
■ Easy
SELECT * FROM employees;
Problem 2: Get only name and salary of all employees
■ Easy
SELECT name, salary FROM employees;
Problem 3: Get unique departments from employees table
■ Easy
SELECT DISTINCT department FROM employees;
■ DAY 2: WHERE Clause
Concepts: WHERE, comparison operators (=, >, <, >=, <=, <>)
Problem 1: Find employees with salary greater than 50000
■ Easy
SELECT * FROM employees WHERE salary > 50000;
Problem 2: Find employees in 'Engineering' department
■ Easy
SELECT * FROM employees WHERE department = 'Engineering';
Problem 3: Find products with price between 100 and 500
■ Easy
SELECT * FROM products WHERE price BETWEEN 100 AND 500;
-- OR
SELECT * FROM products WHERE price >= 100 AND price <= 500;
■ DAY 3: AND, OR, NOT, IN, LIKE
Concepts: Multiple conditions, pattern matching
Problem 1: Find employees in Engineering OR Marketing
■ Easy
SELECT * FROM employees
WHERE department = 'Engineering' OR department = 'Marketing';
-- Better way:
SELECT * FROM employees WHERE department IN ('Engineering', 'Marketing');
Problem 2: Find employees whose name starts with 'A'
■ Easy
SELECT * FROM employees WHERE name LIKE 'A%';
Problem 3: Find employees NOT in Sales department with salary > 40000
■ Easy
SELECT * FROM employees
WHERE department <> 'Sales' AND salary > 40000;
■ LIKE patterns: 'A%' (starts with A), '%a' (ends with a), '%kumar%' (contains kumar), '_a%' (second letter is a)
■ DAY 4: ORDER BY & LIMIT
Concepts: Sorting results, limiting rows
Problem 1: Get top 5 highest paid employees
■ Easy
SELECT * FROM employees ORDER BY salary DESC LIMIT 5;
Problem 2: Get employees sorted by department (A-Z), then by salary (high to low)
■ Easy
SELECT * FROM employees
ORDER BY department ASC, salary DESC;
Problem 3: Get the 3rd highest salary (skip first 2)
■ Medium
SELECT DISTINCT salary FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 2;
■ DAY 5: Aggregate Functions
Concepts: COUNT, SUM, AVG, MIN, MAX
Problem 1: Count total number of employees
■ Easy
SELECT COUNT(*) AS total_employees FROM employees;
Problem 2: Find average, minimum, and maximum salary
■ Easy
SELECT
AVG(salary) AS avg_salary,
MIN(salary) AS min_salary,
MAX(salary) AS max_salary
FROM employees;
Problem 3: Find total sales amount from orders table
■ Easy
SELECT SUM(amount) AS total_sales FROM orders;
■ DAY 6: NULL Handling
Concepts: IS NULL, IS NOT NULL, COALESCE, IFNULL
Problem 1: Find employees without a manager (manager_id is NULL)
■ Easy
SELECT * FROM employees WHERE manager_id IS NULL;
Problem 2: Find employees who have an email address
■ Easy
SELECT * FROM employees WHERE email IS NOT NULL;
Problem 3: Replace NULL bonus with 0
■ Medium
SELECT name, salary, COALESCE(bonus, 0) AS bonus FROM employees;
-- MySQL: IFNULL(bonus, 0)
■ DAY 7: Week 1 Practice Day
Solve these 5 problems to test your Week 1 learning:
P1: Find all customers from 'Mumbai' or 'Delhi' with orders > 1000
P2: Get top 10 products by price, show name and price only
P3: Count customers who have email addresses
P4: Find employees hired in 2023 (use YEAR function or LIKE)
P5: Calculate total revenue, average order value from orders table
■ Week 1 Complete! You should now be comfortable with basic SELECT queries. Practice more on LeetCode Easy
problems.
WEEK 2: JOINs & Grouping
Focus: All JOIN types, GROUP BY, HAVING, Basic Subqueries
■ DAY 8: INNER JOIN
Concepts: Combining tables on matching values
Problem 1: Get employee names with their department names
■ Medium
SELECT [Link], d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = [Link];
Problem 2: Get order details with customer names
■ Medium
SELECT o.order_id, [Link], c.customer_name
FROM orders o
INNER JOIN customers c ON o.customer_id = [Link];
Problem 3: Get products with their category names, only where stock > 0
■ Medium
SELECT p.product_name, c.category_name, [Link]
FROM products p
INNER JOIN categories c ON p.category_id = [Link]
WHERE [Link] > 0;
■ DAY 9: LEFT JOIN & RIGHT JOIN
Concepts: Including non-matching rows
Problem 1: Get ALL customers and their orders (including those with no orders)
■ Medium
SELECT c.customer_name, o.order_id, [Link]
FROM customers c
LEFT JOIN orders o ON [Link] = o.customer_id;
Problem 2: Find customers who have NEVER placed an order
■ Medium — Very commonly asked!
SELECT c.customer_name
FROM customers c
LEFT JOIN orders o ON [Link] = o.customer_id
WHERE o.order_id IS NULL;
Problem 3: Find products that have never been ordered
■ Medium
SELECT p.product_name
FROM products p
LEFT JOIN order_items oi ON [Link] = oi.product_id
WHERE [Link] IS NULL;
■ DAY 10: Self JOIN
Concepts: Joining a table with itself
Problem 1: Find employees and their manager names
■ Medium
SELECT [Link] AS employee, [Link] AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = [Link];
Problem 2: Find employees who earn MORE than their manager
■ Medium — Classic interview question!
SELECT [Link] AS employee, [Link] AS emp_salary,
[Link] AS manager, [Link] AS mgr_salary
FROM employees e
JOIN employees m ON e.manager_id = [Link]
WHERE [Link] > [Link];
■ DAY 11: GROUP BY Basics
Concepts: Grouping rows, aggregating per group
Problem 1: Count employees in each department
■ Medium
SELECT department, COUNT(*) AS employee_count
FROM employees
GROUP BY department;
Problem 2: Find total sales by each customer
■ Medium
SELECT customer_id, SUM(amount) AS total_spent
FROM orders
GROUP BY customer_id
ORDER BY total_spent DESC;
Problem 3: Find average salary by department
■ Medium
SELECT department,
ROUND(AVG(salary), 2) AS avg_salary
FROM employees
GROUP BY department;
■ DAY 12: HAVING Clause
Concepts: Filtering grouped results (WHERE filters rows, HAVING filters groups)
Problem 1: Find departments with more than 5 employees
■ Medium
SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;
Problem 2: Find customers who spent more than 10000 total
■ Medium
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
HAVING SUM(amount) > 10000;
Problem 3: Find products ordered more than 100 times
■ Medium
SELECT product_id, COUNT(*) AS order_count
FROM order_items
GROUP BY product_id
HAVING COUNT(*) > 100;
■ WHERE vs HAVING: WHERE filters before grouping, HAVING filters after grouping. You can't use aggregate functions
in WHERE.
■ DAY 13: Basic Subqueries
Concepts: Query inside a query
Problem 1: Find employees with salary above average
■ Medium
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
Problem 2: Find the second highest salary
■ Medium — Classic!
SELECT MAX(salary) AS second_highest
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);
Problem 3: Find employees in the same department as 'Rahul'
■ Medium
SELECT name FROM employees
WHERE department = (
SELECT department FROM employees WHERE name = 'Rahul'
) AND name <> 'Rahul';
■ DAY 14: Week 2 Practice Day
Solve these 5 problems:
P1: Get all orders with customer name and product name (3-table JOIN)
P2: Find departments where average salary > 60000
P3: Find employees who don't have any direct reports
P4: Get monthly sales totals for 2023
P5: Find customers who placed orders above the average order value
■ Week 2 Complete! JOINs and GROUP BY are the bread and butter of SQL interviews. Practice until they feel natural.
WEEK 3: Advanced SQL
Focus: Window Functions, CTEs, Complex Queries
■ DAY 15: Window Functions Intro (ROW_NUMBER, RANK)
Concepts: Calculations across rows without collapsing them
Problem 1: Rank employees by salary
■ Medium-Hard
SELECT name, salary,
RANK() OVER (ORDER BY salary DESC) AS rank,
DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_num
FROM employees;
Problem 2: Rank employees by salary WITHIN each department
■ Medium-Hard
SELECT name, department, salary,
RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank
FROM employees;
■ RANK: 1,1,3 (gaps) | DENSE_RANK: 1,1,2 (no gaps) | ROW_NUMBER: 1,2,3 (unique)
■ DAY 16: Top N Per Group
Concepts: Using window functions for top N problems
Problem 1: Find top 3 highest paid employees in EACH department
■ Medium-Hard — Very common interview question!
SELECT * FROM (
SELECT name, department, salary,
DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rnk
FROM employees
) ranked
WHERE rnk <= 3;
Problem 2: Find the latest order for each customer
■ Medium-Hard
SELECT * FROM (
SELECT customer_id, order_id, order_date, amount,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) AS rn
FROM orders
) t
WHERE rn = 1;
■ DAY 17: LAG & LEAD
Concepts: Accessing previous/next row values
Problem 1: Compare each day's sales with previous day
■ Medium-Hard
SELECT order_date, amount,
LAG(amount, 1) OVER (ORDER BY order_date) AS prev_day,
amount - LAG(amount, 1) OVER (ORDER BY order_date) AS diff
FROM daily_sales;
Problem 2: Calculate month-over-month growth
■ Medium-Hard
SELECT month, revenue,
LAG(revenue) OVER (ORDER BY month) AS prev_month,
ROUND((revenue - LAG(revenue) OVER (ORDER BY month)) * 100.0 /
LAG(revenue) OVER (ORDER BY month), 2) AS growth_pct
FROM monthly_revenue;
■ DAY 18: Running Totals & Moving Averages
Concepts: Cumulative calculations
Problem 1: Calculate running total of sales
■ Medium-Hard
SELECT order_date, amount,
SUM(amount) OVER (ORDER BY order_date) AS running_total
FROM orders;
Problem 2: Calculate 7-day moving average
■ Hard
SELECT order_date, amount,
AVG(amount) OVER (
ORDER BY order_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS moving_avg_7day
FROM daily_sales;
■ DAY 19: Common Table Expressions (CTEs)
Concepts: WITH clause, readable complex queries
Problem 1: Find employees earning above department average using CTE
■ Medium-Hard
WITH dept_avg AS (
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
)
SELECT [Link], [Link], [Link], d.avg_salary
FROM employees e
JOIN dept_avg d ON [Link] = [Link]
WHERE [Link] > d.avg_salary;
Problem 2: Calculate total and percentage of sales by category
■ Medium-Hard
WITH category_sales AS (
SELECT category, SUM(amount) AS total
FROM sales
GROUP BY category
),
grand_total AS (
SELECT SUM(amount) AS overall FROM sales
)
SELECT [Link], [Link],
ROUND([Link] * 100.0 / [Link], 2) AS percentage
FROM category_sales c, grand_total g;
■ DAY 20: Multiple CTEs & Complex Queries
Problem 1: Year-over-Year comparison with CTEs
■ Hard
WITH yearly_sales AS (
SELECT YEAR(order_date) AS year, SUM(amount) AS total
FROM orders
GROUP BY YEAR(order_date)
),
yoy_comparison AS (
SELECT year, total,
LAG(total) OVER (ORDER BY year) AS prev_year,
total - LAG(total) OVER (ORDER BY year) AS diff
FROM yearly_sales
)
SELECT *, ROUND(diff * 100.0 / prev_year, 2) AS growth_pct
FROM yoy_comparison;
■ DAY 21: Week 3 Practice Day
Solve these problems:
P1: Find the highest selling product in each category
P2: Calculate 30-day running total of sales for each customer
P3: Find employees whose salary increased from last year
P4: Rank customers by total purchases and show top 10%
P5: Calculate percentage contribution of each product to total sales
■ Week 3 Complete! Window functions separate good candidates from great ones. Keep practicing!
WEEK 4: Interview-Level Problems
Focus: Real interview questions from top companies
■ DAY 22: Duplicate Detection & Removal
Problem 1: Find duplicate emails
■ Medium
SELECT email, COUNT(*) AS count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
Problem 2: Delete duplicates, keep lowest ID
■ Hard — Asked at Amazon
DELETE FROM users
WHERE id NOT IN (
SELECT * FROM (
SELECT MIN(id)
FROM users
GROUP BY email
) AS temp
);
■ DAY 23: Consecutive Days/Rows
Problem: Find users who logged in for 3+ consecutive days
■ Hard — Asked at Uber, Airbnb
WITH login_groups AS (
SELECT user_id, login_date,
login_date - INTERVAL ROW_NUMBER() OVER (
PARTITION BY user_id ORDER BY login_date
) DAY AS grp
FROM (SELECT DISTINCT user_id, DATE(login_time) AS login_date FROM logins) t
)
SELECT user_id, MIN(login_date) AS start_date,
MAX(login_date) AS end_date, COUNT(*) AS streak
FROM login_groups
GROUP BY user_id, grp
HAVING COUNT(*) >= 3;
■ DAY 24: Pivot / Transpose Data
Problem: Convert rows to columns (sales by month)
■ Hard
SELECT product_id,
SUM(CASE WHEN month = 'Jan' THEN amount ELSE 0 END) AS Jan,
SUM(CASE WHEN month = 'Feb' THEN amount ELSE 0 END) AS Feb,
SUM(CASE WHEN month = 'Mar' THEN amount ELSE 0 END) AS Mar
FROM sales
GROUP BY product_id;
■ DAY 25: Finding Gaps in Data
Problem: Find missing IDs in a sequence
■ Hard — Asked at LinkedIn
SELECT [Link] + 1 AS gap_start,
MIN([Link]) - 1 AS gap_end
FROM numbers a
JOIN numbers b ON [Link] < [Link]
WHERE NOT EXISTS (
SELECT 1 FROM numbers c WHERE [Link] = [Link] + 1
)
GROUP BY [Link];
■ DAY 26: Retention & Churn Analysis
Problem: Calculate monthly user retention rate
■ Hard — Product Analytics favorite
WITH monthly_users AS (
SELECT DISTINCT user_id, DATE_FORMAT(activity_date, '%Y-%m') AS month
FROM user_activity
)
SELECT [Link],
COUNT(DISTINCT a.user_id) AS total_users,
COUNT(DISTINCT b.user_id) AS retained_users,
ROUND(COUNT(DISTINCT b.user_id) * 100.0 / COUNT(DISTINCT a.user_id), 2) AS retention_rate
FROM monthly_users a
LEFT JOIN monthly_users b ON a.user_id = b.user_id
AND [Link] = DATE_FORMAT(DATE_ADD(STR_TO_DATE(CONCAT([Link], '-01'), '%Y-%m-%d'), INTERVAL 1 MONTH),
GROUP BY [Link];
■ DAY 27: Median Calculation
Problem: Find median salary
■ Hard
WITH ranked AS (
SELECT salary,
ROW_NUMBER() OVER (ORDER BY salary) AS rn,
COUNT(*) OVER () AS total
FROM employees
)
SELECT AVG(salary) AS median
FROM ranked
WHERE rn IN (FLOOR((total + 1) / 2.0), CEIL((total + 1) / 2.0));
■ DAY 28: Recursive CTEs
Problem: Find entire reporting hierarchy under a manager
■ Hard
WITH RECURSIVE hierarchy AS (
-- Base: start with the top manager
SELECT id, name, manager_id, 1 AS level
FROM employees
WHERE id = 1
UNION ALL
-- Recursive: find all reports
SELECT [Link], [Link], e.manager_id, [Link] + 1
FROM employees e
JOIN hierarchy h ON e.manager_id = [Link]
)
SELECT * FROM hierarchy;
■ DAY 29: Business Case Problems
Problem 1: Find customers who bought A and B but not C
■ Hard
SELECT customer_id
FROM orders
GROUP BY customer_id
HAVING SUM(CASE WHEN product = 'A' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN product = 'B' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN product = 'C' THEN 1 ELSE 0 END) = 0;
Problem 2: Find products with declining sales for 3 consecutive months
■ Hard
WITH monthly AS (
SELECT product_id, month, total,
LAG(total, 1) OVER (PARTITION BY product_id ORDER BY month) AS prev1,
LAG(total, 2) OVER (PARTITION BY product_id ORDER BY month) AS prev2
FROM monthly_sales
)
SELECT product_id, month
FROM monthly
WHERE total < prev1 AND prev1 < prev2;
■ DAY 30: Final Challenge Day!
Solve these without looking at solutions. Time yourself (45 mins).
Challenge 1: Top 3 salaries in each department
Challenge 2: Employees earning more than department average
Challenge 3: Second highest salary (handle ties)
Challenge 4: Running total of sales by customer
Challenge 5: Find managers with at least 5 direct reports
Practice Resources
Platform Best For Link
LeetCode Interview prep [Link]/problemset/database
HackerRank Beginners [Link]/domains/sql
StrataScratch Real interview Qs [Link]
SQLZoo Interactive learning [Link]
Mode SQL Tutorial Practice datasets [Link]/sql-tutorial
DataLemur FAANG questions [Link]
30-Day Progress Tracker
Print this and check off each day:
■ ■ ■ ■ ■ ■ ■ Week 1
■ ■ ■ ■ ■ ■ ■ Week 2
■ ■ ■ ■ ■ ■ ■ Week 3
■ ■ ■ ■ ■ ■ ■ ■ ■ Week 4
You've completed the 30-Day SQL Challenge! ■ You're now ready to crack SQL interviews. Keep practicing, stay
consistent, and go get that job! ■