Database Administrator MySQL Practice Problems with Real-World Scenarios & Solutions
Database Administrator MySQL Practice Problems with Real-World Scenarios & Solutions

Beginner Level Problems
1. Customer Database Query
Scenario:
You're working with an e-commerce database. The customers
table contains: customer_id
, name
, email
, join_date
, and premium_member
(boolean).
Problem:
Find all customers who joined in 2023 and are premium members.
Solution:
SELECT name, email FROM customers WHERE YEAR(join_date) = 2023 AND premium_member = TRUE;
2. Inventory Management
Scenario:
Your products
table tracks: product_id
, name
, category
, price
, and stock_quantity
.
Problem:
List all electronics products with less than 50 items in stock, sorted by price (high to low).
Solution:
SELECT name, price FROM products WHERE category = 'Electronics' AND stock_quantity < 50 ORDER BY price DESC;
Intermediate Level Problems
3. Hospital Patient Analysis
Scenario:
A hospital database has:
-
patients
(patient_id, name, birth_date) -
visits
(visit_id, patient_id, visit_date, doctor_id) -
doctors
(doctor_id, name, specialty)
Problem:
Find patients who visited cardiologists more than twice in 2023.
Solution:
SELECT p.name, COUNT(*) AS cardiology_visits FROM patients p JOIN visits v ON p.patient_id = v.patient_id JOIN doctors d ON v.doctor_id = d.doctor_id WHERE d.specialty = 'Cardiology' AND YEAR(v.visit_date) = 2023 GROUP BY p.patient_id, p.name HAVING COUNT(*) > 2;
4. University Course Enrollment
Scenario:
University database with:
-
students
(student_id, name, major) -
courses
(course_id, title, department) -
enrollments
(enrollment_id, student_id, course_id, semester)
Problem:
Identify computer science courses with enrollment exceeding capacity (50 students) in Fall 2023.
Solution:
SELECT c.title, COUNT(*) AS enrolled_students FROM courses c JOIN enrollments e ON c.course_id = e.course_id WHERE c.department = 'Computer Science' AND e.semester = 'Fall2023' GROUP BY c.course_id, c.title HAVING COUNT(*) > 50;
Advanced Level Problems
5. Financial Transaction Analysis
Scenario:
Bank database with:
-
accounts
(account_id, customer_id, balance, open_date) -
transactions
(transaction_id, account_id, amount, transaction_date, type)
Problem:
Find accounts with suspicious activity (3+ withdrawals over $5,000 in a 7-day period).
Solution:
SELECT a.account_id, c.name, COUNT(*) AS large_withdrawals FROM accounts a JOIN transactions t ON a.account_id = t.account_id JOIN customers c ON a.customer_id = c.customer_id WHERE t.type = 'withdrawal' AND t.amount > 5000 GROUP BY a.account_id, c.name, t.transaction_date HAVING COUNT(*) >= 3 AND DATEDIFF(MAX(t.transaction_date), MIN(t.transaction_date)) <= 7;
6. Airline Flight Optimization
Scenario:
Airline database tracks:
-
flights
(flight_id, route_id, departure_time, arrival_time, aircraft_id) -
routes
(route_id, origin, destination, distance) -
bookings
(booking_id, flight_id, passenger_id, seat_class)
Problem:
Identify routes where business class occupancy is below 40% for the last quarter.
Solution:
WITH business_seats AS ( SELECT f.route_id, r.origin, r.destination, COUNT(CASE WHEN b.seat_class = 'Business' THEN 1 END) AS business_booked, (SELECT COUNT(*) FROM aircraft_seats WHERE aircraft_id = f.aircraft_id AND class = 'Business') AS total_business_seats FROM flights f JOIN routes r ON f.route_id = r.route_id JOIN bookings b ON f.flight_id = b.flight_id WHERE f.departure_time BETWEEN DATE_SUB(NOW(), INTERVAL 3 MONTH) AND NOW() GROUP BY f.route_id, r.origin, r.destination, f.aircraft_id ) SELECT origin, destination, business_booked, total_business_seats, (business_booked/total_business_seats)*100 AS occupancy_rate FROM business_seats WHERE (business_booked/total_business_seats) < 0.4;
Expert Level Challenges
7. Retail Price Optimization
Scenario:
E-commerce database with:
-
products
(product_id, name, current_price, cost) -
sales
(sale_id, product_id, sale_date, quantity, price_sold) -
competitor_prices
(comp_id, product_id, comp_price, date_recorded)
Problem:
Recommend price adjustments for products where:
-
Our price is >20% higher than average competitor price
-
Sales volume dropped >15% last month
-
Current profit margin >30%
Solution:
WITH current_stats AS ( SELECT p.product_id, p.name, p.current_price, AVG(cp.comp_price) AS avg_comp_price, (p.current_price - p.cost)/p.current_price AS current_margin, SUM(CASE WHEN s.sale_date BETWEEN DATE_SUB(NOW(), INTERVAL 2 MONTH) AND DATE_SUB(NOW(), INTERVAL 1 MONTH) THEN s.quantity ELSE 0 END) AS prev_month_sales, SUM(CASE WHEN s.sale_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW() THEN s.quantity ELSE 0 END) AS last_month_sales FROM products p LEFT JOIN sales s ON p.product_id = s.product_id LEFT JOIN competitor_prices cp ON p.product_id = cp.product_id GROUP BY p.product_id, p.name, p.current_price, p.cost ) SELECT product_id, name, current_price, ROUND(avg_comp_price, 2) AS competitor_avg, ROUND(current_margin*100, 1) AS margin_percent, CASE WHEN last_month_sales = 0 THEN -100 ELSE ROUND((last_month_sales-prev_month_sales)/prev_month_sales*100, 1) END AS sales_change_percent, CONCAT('Recommended new price: $', ROUND(avg_comp_price*1.1, 2)) AS price_recommendation FROM current_stats WHERE current_price > avg_comp_price*1.2 AND ((last_month_sales-prev_month_sales)/prev_month_sales) < -0.15 AND current_margin > 0.3;
8. Smart City Traffic Analysis
Scenario:
City transportation database tracks:
-
traffic_sensors
(sensor_id, location, highway, lane_count) -
traffic_readings
(reading_id, sensor_id, timestamp, speed, vehicle_count) -
incidents
(incident_id, location, start_time, end_time, severity)
Problem:
Create a traffic congestion early warning system that identifies:
-
Locations with speed drop >30% compared to historical average
-
Where vehicle count is >20% above average
-
With no existing reported incidents
Solution:
WITH historical_avg AS ( SELECT sensor_id, AVG(speed) AS avg_speed, AVG(vehicle_count) AS avg_vehicles FROM traffic_readings WHERE timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 3 MONTH) AND DATE_SUB(NOW(), INTERVAL 1 DAY) GROUP BY sensor_id ), current_readings AS ( SELECT r.sensor_id, s.location, s.highway, r.speed, r.vehicle_count, h.avg_speed, h.avg_vehicles FROM traffic_readings r JOIN traffic_sensors s ON r.sensor_id = s.sensor_id JOIN historical_avg h ON r.sensor_id = h.sensor_id WHERE r.timestamp >= DATE_SUB(NOW(), INTERVAL 1 HOUR) ) SELECT cr.location, cr.highway, cr.speed AS current_speed, ROUND(cr.avg_speed, 1) AS historical_speed, cr.vehicle_count AS current_vehicles, ROUND(cr.avg_vehicles) AS historical_vehicles, CASE WHEN (cr.avg_speed - cr.speed)/cr.avg_speed > 0.3 AND (cr.vehicle_count - cr.avg_vehicles)/cr.avg_vehicles > 0.2 THEN 'CONGESTION WARNING' ELSE 'Normal' END AS status FROM current_readings cr WHERE NOT EXISTS ( SELECT 1 FROM incidents i WHERE i.location = cr.location AND i.end_time IS NULL ) HAVING status = 'CONGESTION WARNING';
Key Features of These Scenarios
✅ Real-world business cases from multiple industries
✅ Progressive difficulty with complete solutions
✅ Practical SQL techniques for data analysis
✅ Optimized queries following best practices
✅ Comprehensive scenarios with multiple tables