Hands-On SQL Practice with the Query Emulator
Practice Makes Perfect
You've learned SQL syntax, explored aggregate functions, mastered joins, and understood transactions. Now it's time to practice. Reading about SQL and writing SQL are two very different skills – the only way to become proficient is through hands-on experience.
This lesson provides an interactive SQL query emulator that runs entirely in your browser. It uses the same e-commerce schema you've seen throughout the SQL lessons: Users, Categories, Products, Orders, and OrderItems. The database is pre-populated with realistic test data.
You can write queries, execute them instantly, and see results – all without installing a database server or setting up any infrastructure. The emulator supports the core SQL features you've learned, and its logic has been thoroughly tested against the challenge queries below to ensure accuracy and reliability:
SELECTwith specific columns or*WHEREclauses with comparison operators (=,>,<,>=,<=,!=)AND,OR,NOTlogical operatorsIN,BETWEEN,LIKEoperatorsORDER BYwithASC/DESCLIMITfor result pagination- Aggregate functions:
COUNT(),SUM(),AVG(),MIN(),MAX() GROUP BYwithHAVINGINNER JOINandLEFT JOINUNIONandUNION ALLCASEexpressionsCOALESCEandNULLIFEXISTSandNOT EXISTS
⚠️ Please note: while the emulator has been validated on these queries, more advanced or untested SQL patterns may not behave exactly as they would in a production database.
The challenges below start simple and gradually increase in complexity, helping you build confidence and proficiency.
Database Schema
Here's the e-commerce database structure you'll be working with. Understanding these relationships is crucial for writing effective queries, especially when using JOIN operations.
Reading the Schema
- PK (Primary Key): Uniquely identifies each record in the table
- FK (Foreign Key): References a primary key in another table, creating relationships
- Lines between tables: Show how data connects – for example, each Order belongs to one User
The Query Emulator
Below is the interactive SQL emulator. Type your queries in the text area and click "Run Query" to see results. The emulator shows you the resulting data table, the number of rows returned, and any error messages if your query has syntax issues.
Emulator Tips
- Start simple: Begin with basic
SELECT * FROM Usersto see the data structure - Case-insensitive: SQL keywords work in any case (
SELECTorselect) - Check your results: The emulator displays row counts and execution feedback
- Experiment freely: This is a read-only emulator – you can't break anything!
SQL Query Emulator
Practice Challenges
Work through these challenges to build your SQL skills. Start with Level 1 and progress to more complex queries. Try solving each challenge before looking at the solution.
Level 1: Basic Queries
Challenge 1.1: Select all columns from the Users table.
Show Solution
SELECT * FROM Users;
Challenge 1.2: Select only the ProductId, Name, and Price columns from the Products table.
Show Solution
SELECT ProductId, Name, Price FROM Products;
Challenge 1.3: Find all active users (where IsActive = 1).
Show Solution
SELECT * FROM Users WHERE IsActive = 1;
Challenge 1.4: Find all products with a price greater than $50.
Show Solution
SELECT * FROM Products WHERE Price > 50;
Challenge 1.5: List all products, ordered by price from highest to lowest.
Show Solution
SELECT * FROM Products ORDER BY Price DESC;
Level 2: Filtering and Sorting
Challenge 2.1: Find all orders with status 'Completed' that have a total amount greater than $100.
Show Solution
SELECT * FROM Orders
WHERE Status = 'Completed' AND TotalAmount > 100;
Challenge 2.2: Find products with prices between $20 and $100.
Show Solution
SELECT * FROM Products
WHERE Price BETWEEN 20 AND 100;
Challenge 2.3: Find all users whose email contains 'gmail.com'.
Show Solution
SELECT * FROM Users
WHERE Email LIKE '%gmail.com%';
Challenge 2.4: Show the 5 most expensive products.
Show Solution
SELECT * FROM Products
ORDER BY Price DESC
LIMIT 5;
Challenge 2.5: Find orders with status of either 'Pending' or 'Processing'.
Show Solution
SELECT * FROM Orders
WHERE Status IN ('Pending', 'Processing');
Level 3: Aggregate Functions
Challenge 3.1: Count the total number of users in the database.
Show Solution
SELECT COUNT(*) AS TotalUsers FROM Users;
Challenge 3.2: Calculate the average price of all products.
Show Solution
SELECT AVG(Price) AS AveragePrice FROM Products;
Challenge 3.3: Find the total revenue from all completed orders.
Show Solution
SELECT SUM(TotalAmount) AS TotalRevenue
FROM Orders
WHERE Status = 'Completed';
Challenge 3.4: Find the minimum and maximum product prices.
Show Solution
SELECT MIN(Price) AS MinPrice, MAX(Price) AS MaxPrice
FROM Products;
Level 4: GROUP BY and Aggregation
Challenge 4.1: Count how many orders each user has placed.
Show Solution
SELECT UserId, COUNT(*) AS OrderCount
FROM Orders
GROUP BY UserId;
Challenge 4.2: Calculate average price and total stock for each category.
Show Solution
SELECT CategoryId,
AVG(Price) AS AvgPrice,
SUM(StockQuantity) AS TotalStock
FROM Products
GROUP BY CategoryId;
Challenge 4.3: Find users who have placed more than 2 orders.
Show Solution
SELECT UserId, COUNT(*) AS OrderCount
FROM Orders
GROUP BY UserId
HAVING COUNT(*) > 2;
Challenge 4.4: Show order counts by status, ordered from most to least common.
Show Solution
SELECT Status, COUNT(*) AS Count
FROM Orders
GROUP BY Status
ORDER BY Count DESC;
Level 5: JOINs
Challenge 5.1: Show all orders with the user's first and last name.
Show Solution
SELECT o.OrderId, o.OrderDate, o.TotalAmount,
u.FirstName, u.LastName
FROM Orders o
INNER JOIN Users u ON o.UserId = u.UserId;
Challenge 5.2: Show all products with their category names.
Show Solution
SELECT p.ProductId, p.Name, p.Price, c.CategoryName
FROM Products p
INNER JOIN Categories c ON p.CategoryId = c.CategoryId;
Challenge 5.3: List all users with their order count (including users with zero orders).
Show Solution
SELECT u.UserId, u.Email, COUNT(o.OrderId) AS OrderCount
FROM Users u
LEFT JOIN Orders o ON u.UserId = o.UserId
GROUP BY u.UserId, u.Email;
Challenge 5.4: Show order details with product names (join Orders → OrderItems → Products).
Show Solution
SELECT o.OrderId, oi.Quantity, p.Name, oi.UnitPrice
FROM Orders o
INNER JOIN OrderItems oi ON o.OrderId = oi.OrderId
INNER JOIN Products p ON oi.ProductId = p.ProductId;
Level 6: Advanced Queries
Challenge 6.1: Find products more expensive than the average product price.
Show Solution
SELECT * FROM Products
WHERE Price > (SELECT AVG(Price) FROM Products);
Challenge 6.2: Categorize products by price range using CASE.
Show Solution
SELECT Name, Price,
CASE
WHEN Price < 30 THEN 'Budget'
WHEN Price BETWEEN 30 AND 100 THEN 'Mid-Range'
ELSE 'Premium'
END AS PriceCategory
FROM Products;
Challenge 6.3: Combine active and inactive users into one result with a status label.
Show Solution
SELECT UserId, Email, 'Active' AS Status
FROM Users WHERE IsActive = 1
UNION ALL
SELECT UserId, Email, 'Inactive' AS Status
FROM Users WHERE IsActive = 0;
Challenge 6.4: Calculate revenue per user for users with completed orders.
Show Solution
SELECT u.UserId, u.Email,
COALESCE(SUM(o.TotalAmount), 0) AS TotalRevenue
FROM Users u
LEFT JOIN Orders o ON u.UserId = o.UserId AND o.Status = 'Completed'
GROUP BY u.UserId, u.Email
ORDER BY TotalRevenue DESC;
Keep experimenting with different query combinations. The more you practice, the more natural SQL will become!