20 SQL Practice Problems for Beginners with Solutions

New to SQL? This practice set is designed for complete beginners. You'll work through 20 problems covering the five most fundamental SQL concepts — SELECT, WHERE, ORDER BY, LIMIT, and COUNT — with full solutions and plain-English explanations for every problem. No prior experience needed. Click any problem to reveal the solution.

Part 1 — SELECT (Problems 1–3)

SELECT is the first clause in almost every SQL query. It tells the database which columns you want to see. Think of it like choosing which columns to display from a spreadsheet.

💡 Basic syntax: SELECT column1, column2 FROM table_name; — Use SELECT * to return every column.
Problem 1 Show the name and price of every item on the menu. Table: menu_items
Columns: item_id, item_name, category, price_usd, calories
Show solution ↓

Solution

SELECT item_name, price_usd
FROM menu_items;

Explanation

SELECT tells the database which columns to return. By listing item_name and price_usd, only those two columns appear in the results — all other columns like category and calories are left out. FROM tells the database which table to pull from.

Problem 2 Show every column and every row from the menu items table. Table: menu_items
Columns: item_id, item_name, category, price_usd, calories
Show solution ↓

Solution

SELECT *
FROM menu_items;

Explanation

The asterisk (*) is a shorthand that means "give me every column." This is useful when you're exploring a table for the first time and want to see all the data. Every row and every column in the table will be returned.

Problem 3 Show the first name, last name, and email address of every customer. Table: customers
Columns: customer_id, first_name, last_name, email, signup_date, city
Show solution ↓

Solution

SELECT first_name, last_name, email
FROM customers;

Explanation

Listing three column names after SELECT tells the database to return only those three columns for every row. The customer_id, signup_date, and city columns are excluded from the results because they weren't listed.

Part 2 — WHERE (Problems 4–6)

WHERE filters the rows returned by a query. Without it, you get every row in the table. Adding WHERE lets you say "only show me rows where this condition is true."

💡 Basic syntax: SELECT * FROM table_name WHERE column = 'value'; — Use single quotes around text values. Numbers don't need quotes.
Problem 4 Show all columns for menu items in the Dessert category. Table: menu_items
Columns: item_id, item_name, category, price_usd, calories
Show solution ↓

Solution

SELECT *
FROM menu_items
WHERE category = 'Dessert';

Explanation

WHERE category = 'Dessert' tells the database to only return rows where the category column equals 'Dessert'. Every other row is filtered out. Notice the text value is wrapped in single quotes — this is required for text comparisons in SQL.

Problem 5 Find all customers who signed up from New York. Table: customers
Columns: customer_id, first_name, last_name, email, signup_date, city
Show solution ↓

Solution

SELECT *
FROM customers
WHERE city = 'New York';

Explanation

WHERE city = 'New York' filters the results so only customers from New York are returned. All customers from other cities are excluded. SELECT * means all columns are shown for the matching rows.

Problem 6 Show all columns for products that cost more than $50. Table: products
Columns: product_id, product_name, category, price_usd, stock_quantity
Show solution ↓

Solution

SELECT *
FROM products
WHERE price_usd > 50;

Explanation

WHERE price_usd > 50 filters to only rows where the price is greater than 50. Notice there are no quotes around the number — in SQL, quotes are only used for text values, never for numbers. Every product priced at $50 or less is excluded.

Part 3 — ORDER BY (Problems 7–9)

By default SQL returns rows in no particular order. ORDER BY lets you sort the results by any column — either ascending (A to Z, smallest to largest) or descending (Z to A, largest to smallest).

💡 Basic syntax: ORDER BY column_name; sorts ascending by default. Add DESC for descending. ORDER BY always goes at the end of your query.
Problem 7 Show every product's name and price, sorted from cheapest to most expensive. Table: products
Columns: product_id, product_name, category, price_usd, stock_quantity
Show solution ↓

Solution

SELECT product_name, price_usd
FROM products
ORDER BY price_usd;

Explanation

ORDER BY price_usd sorts the results by price. When you don't specify ASC or DESC, SQL defaults to ascending order — meaning the lowest price appears first. This is the correct behavior for "cheapest to most expensive."

Problem 8 Show every customer's first name and signup date, sorted from most recent signup to oldest. Table: customers
Columns: customer_id, first_name, last_name, email, signup_date, city
Show solution ↓

Solution

SELECT first_name, signup_date
FROM customers
ORDER BY signup_date DESC;

Explanation

ORDER BY signup_date DESC sorts dates in descending order — most recent first, oldest last. Without DESC, the oldest signup date would appear first. Always add DESC when you want newest, largest, or highest values at the top.

Problem 9 Show every menu item's name and category, sorted alphabetically by item name. Table: menu_items
Columns: item_id, item_name, category, price_usd, calories
Show solution ↓

Solution

SELECT item_name, category
FROM menu_items
ORDER BY item_name;

Explanation

ORDER BY item_name sorts text columns alphabetically from A to Z by default. This makes it easy to scan through menu items in alphabetical order. If you wanted Z to A, you'd add DESC.

Part 4 — LIMIT (Problems 10–12)

LIMIT restricts how many rows are returned by a query. It's useful when a table has thousands of rows and you only need to see a few — for example, the top 5 results or just a quick sample of the data.

💡 Basic syntax: Add LIMIT 10 at the very end of your query to return only the first 10 rows. Combine with ORDER BY to get the top or bottom N results.
Problem 10 Show the first 5 rows from the products table. Table: products
Columns: product_id, product_name, category, price_usd, stock_quantity
Show solution ↓

Solution

SELECT *
FROM products
LIMIT 5;

Explanation

LIMIT 5 tells the database to stop returning rows after the first 5. This is useful when you just want a quick look at what a table contains without retrieving thousands of rows. SELECT * returns all columns for those 5 rows.

Problem 11 Show the 3 most expensive menu items. Return the item name and price. Table: menu_items
Columns: item_id, item_name, category, price_usd, calories
Show solution ↓

Solution

SELECT item_name, price_usd
FROM menu_items
ORDER BY price_usd DESC
LIMIT 3;

Explanation

ORDER BY price_usd DESC sorts all items from most to least expensive first. Then LIMIT 3 keeps only the top 3 rows from that sorted result. This ORDER BY + LIMIT combination is the standard pattern for finding the top N results in SQL.

Problem 12 Show the 10 most recently signed up customers. Return their first name and signup date. Table: customers
Columns: customer_id, first_name, last_name, email, signup_date, city
Show solution ↓

Solution

SELECT first_name, signup_date
FROM customers
ORDER BY signup_date DESC
LIMIT 10;

Explanation

ORDER BY signup_date DESC puts the most recent signups at the top. LIMIT 10 then keeps only the first 10 rows from that sorted list — giving you the 10 most recently signed up customers.

Part 5 — COUNT (Problems 13–15)

COUNT is an aggregate function that counts the number of rows in a table or group. It's one of the most commonly used functions in SQL and is often combined with WHERE to count rows that meet a specific condition.

💡 Basic syntax: SELECT COUNT(*) FROM table_name; counts every row. Add WHERE to count only rows that match a condition.
Problem 13 Count the total number of customers in the table. Table: customers
Columns: customer_id, first_name, last_name, email, signup_date, city
Show solution ↓

Solution

SELECT COUNT(*) AS total_customers
FROM customers;

Explanation

COUNT(*) counts every row in the table regardless of what values the columns contain. AS total_customers gives the result a readable column name instead of just showing "COUNT(*)". The result is a single number — the total number of rows in the customers table.

Problem 14 Count how many products are in the Electronics category. Table: products
Columns: product_id, product_name, category, price_usd, stock_quantity
Show solution ↓

Solution

SELECT COUNT(*) AS electronics_count
FROM products
WHERE category = 'Electronics';

Explanation

WHERE category = 'Electronics' filters the rows first, keeping only Electronics products. COUNT(*) then counts how many rows remain after that filter. Combining WHERE with COUNT is how you count rows that meet a specific condition.

Problem 15 Count how many menu items cost less than $10. Table: menu_items
Columns: item_id, item_name, category, price_usd, calories
Show solution ↓

Solution

SELECT COUNT(*) AS affordable_items
FROM menu_items
WHERE price_usd < 10;

Explanation

WHERE price_usd < 10 filters to only rows where the price is below $10. COUNT(*) counts how many rows match that condition. The result is a single number telling you how many menu items are priced under $10.

Part 6 — Combined (Problems 16–20)

Real SQL queries almost always combine multiple clauses. These problems combine two of the concepts you've just practiced. Try to write the query before revealing the solution — you have everything you need.

Problem 16 — SELECT + WHERE Show the name and price of all menu items that have fewer than 500 calories. Table: menu_items
Columns: item_id, item_name, category, price_usd, calories
Show solution ↓

Solution

SELECT item_name, price_usd
FROM menu_items
WHERE calories < 500;

Explanation

SELECT chooses which columns to display — just item_name and price_usd. WHERE calories < 500 filters the rows so only low-calorie items appear. The calories column itself doesn't need to be in your SELECT list to use it as a filter condition.

Problem 17 — WHERE + ORDER BY Show all columns for products in the Clothing category, sorted from most to least expensive. Table: products
Columns: product_id, product_name, category, price_usd, stock_quantity
Show solution ↓

Solution

SELECT *
FROM products
WHERE category = 'Clothing'
ORDER BY price_usd DESC;

Explanation

WHERE category = 'Clothing' filters to only Clothing products. ORDER BY price_usd DESC then sorts those filtered results from most to least expensive. The clause order matters — WHERE always comes before ORDER BY.

Problem 18 — ORDER BY + LIMIT Show the 5 lowest-calorie items on the menu. Return the item name and calories. Table: menu_items
Columns: item_id, item_name, category, price_usd, calories
Show solution ↓

Solution

SELECT item_name, calories
FROM menu_items
ORDER BY calories
LIMIT 5;

Explanation

ORDER BY calories sorts all items from lowest to highest calorie count. LIMIT 5 then keeps only the first 5 rows from that sorted list — giving the 5 lowest-calorie items. No DESC is needed here because we want the lowest values first, which is the default ascending order.

Problem 19 — WHERE + COUNT Count how many customers signed up from Chicago. Table: customers
Columns: customer_id, first_name, last_name, email, signup_date, city
Show solution ↓

Solution

SELECT COUNT(*) AS chicago_customers
FROM customers
WHERE city = 'Chicago';

Explanation

WHERE city = 'Chicago' filters to only Chicago customers. COUNT(*) then counts how many rows match. The result is a single number — the total count of customers from Chicago. AS chicago_customers gives the result column a clear, readable name.

Problem 20 — WHERE + ORDER BY + LIMIT Show the 3 most expensive products in the Electronics category. Return the product name and price. Table: products
Columns: product_id, product_name, category, price_usd, stock_quantity
Show solution ↓

Solution

SELECT product_name, price_usd
FROM products
WHERE category = 'Electronics'
ORDER BY price_usd DESC
LIMIT 3;

Explanation

This query uses three clauses together. WHERE category = 'Electronics' filters to only Electronics products. ORDER BY price_usd DESC sorts those products from most to least expensive. LIMIT 3 keeps only the top 3 from that sorted list. This is a great example of how SQL clauses build on each other — filter first, sort second, limit third.

Ready to practice writing these queries yourself? Try the SQL Drills interactive beginner exercises — write real queries and get instant feedback.

Try Beginner Exercises Interactively →

Feeling confident with the basics? Try the intermediate SQL exercises next, or head back to the SQL Drills Learn hub for more practice sets and guides.