SQL Tutorial
Sql database, sql references, sql examples, sql exercises.
Test your SQL skills with exercises from all categories:
Select Distinct
Insert into, null values, min and max, select into, insert into select, case expression, null functions, stored procedures, create database, drop database, backup database, create table, alter table, constraints, primary key, foreign key, create index, auto increment, log in to track your progress.
If you haven't already, sign up to become a W3Schooler, and get points for every exercise you complete.
As a logged on W3Schools user you will have access to many features like having your own web page , track your learning progress , receive personal guided paths , and more .
The Exercise
The exercises are a mix of "multiple choice" and "fill in the blanks" questions. There are between 3 and 9 questions in each catergory. The answer can be found in the corresponding tutorial chapter. If you're stuck, or answer wrong, you can try again or hit the "Show Answer" button to see the correct answer.
Kickstart your career
Get certified by completing the course
COLOR PICKER
Contact Sales
If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail: [email protected]
Report Error
If you want to report an error, or if you want to make a suggestion, send us an e-mail: [email protected]
Top Tutorials
Top references, top examples, get certified.
15 SQL Server Practice Exercises with Solutions
- online practice
- MS SQL Server
Table of Contents
Exercise 1: Get to Know the Cat Table
Exercise 2: kittens, exercise 3: young and old ragdoll cats, exercise 4: which cats like to play with balls, exercise 5: average production costs for good games, exercise 6: game production statistics by year, exercise 7: company production statistics, exercise 8: identify good games, exercise 9: gross profit by company, exercise 10: list all pieces of art, exercise 11: works from 19th-century artists (and later), exercise 12: artists' productivity, exercise 13: revenue for each order, exercise 14: who repurchased products, exercise 15: how much did each client spend per category, further sql server practice.
Enhance your SQL Server proficiency with our SQL Server practice exercises. Each of these 15 practical T-SQL tasks includes a detailed solution to help you improve your querying skills.
You know how everyone says, "Practice makes perfect"? Well, it couldn't be truer for SQL. The real learning happens when you start working with queries, tables, and data. If you're looking to sharpen your skills in MS SQL Server, you're in the right spot. These 15 beginner-friendly T-SQL exercises are perfect for getting the hang of the basics. (If you’re wondering, T-SQL is the SQL dialect used in SQL Server databases.)
The exercises are taken from our interactive course SQL Practice Set in MS SQL Server . This is a T-SQL practice course for beginners working with SQL Server. It offers over 80 hands-on practical exercises , grouped into sections on single table queries, aggregate functions, grouping and ordering results, JOINS , and subqueries, and others. If you like the exercises in this article, I recommend you try the course !
If you’re a beginner who wants to learn everything T-SQL has to offer, check out our complete learning track SQL from A to Z in MS SQL Server . The track contains 7 interactive T-SQL courses that will teach you complete modern T-SQL for data analysis.
Section 1: Cats – Purr-fect SQL Exercises to Sharpen Your Claws
In the first section, we’ll work on the table Cat . This table has the following columns:
- Id – The ID of a given cat.
- Name – The cat’s name.
- Breed – The cat’s breed (e.g. Siamese, Cornish Rex).
- Coloration – The cat’s coloration (e.g. tortoiseshell, black).
- Age – The cat’s age.
- Sex – The cat’s sex.
- FavToy – The cat’s favorite toy.
Exercise: Select all data from the Cat table.
Solution: We use the SELECT statement to select data from the database. The asterisk ( * ) following SELECT means that you want all columns from the table. The FROM Cat command indicates the table from which you pull the rows.
Exercise: Select the Name , Breed , and Coloration for every cat that is younger than five years old.
Explanation: As before, we use the SELECT statement. This time, we list the columns we want to select: Name , Breed , and Coloration . In the FROM clause, we give the name of the table ( Cats ).
In the WHERE clause, we specify the condition to only select cats younger than 5 years old: Age < 5 . We use the < operator to compare the value of the Age column with the number 5. The database will only select the cats who are younger than 5 (i.e. have Age lower than 5).
Exercise: Select the ID and name for every cat that is either younger than five years old or older than ten years old and that is of the Ragdoll breed .
Explanation: This query is similar to the previous query. The only difference is in the WHERE clause.
We are looking for cats who are younger than 5 or older than 10. To this end, we use the condition ( Age < 5 OR Age > 10 ). We use the comparison operators < and > , and we combine them with the logical operator OR . This selects cats who are either younger than 5 or older than 10.
We then use the condition Breed = 'Ragdoll' to only select Ragdoll cats. It’s important to note that the text value Ragdoll is put in single quotes: 'Ragdoll' .
Finally, we use the AND operator to combine the age and breed conditions.
Exercise: Select all data for cats whose:
- Breed starts with an 'R'.
- Coloration ends with an 'm'.
- Favorite toy starts with the word 'ball'.
Explanation: We use a simple SELECT query to solve the exercise. In SELECT , we put the asterisk * to select all columns from the table.
We then use AND to combine three WHERE conditions. The first condition selects cats with breed names starting with R. We use the LIKE operator and the wildcard % : Breed LIKE 'R%' . This condition means that we are looking for breeds that start with R, followed by any text (empty or not).
In the second condition, we use Coloration LIKE '%m' to find cats whose coloration ends in “m”. In the third condition, we use FavToy LIKE 'ball%' to look for favorite toys that start with “ball”.
If you are looking for additional basic SQL exercises, check out our article 10 Beginner SQL Practice Exercises with Solutions .
Section 2: Games – Level Up Your SQL Skills with Video Game Data
Now we move on from cats and focus on something completely different: video games. We’ll work with the Games table, which consists of 9 columns:
- Id – The ID of a given game.
- Title – The game ‘s title (e.g. Mario Kart).
- Company – The company that produced the game.
- Type – The genre (e.g. racing).
- ProductionYear – The year when the game was created.
- System – The system for which the game was released (e.g. Nintendo).
- ProductionCost – The cost of producing the game.
- Revenue – The revenue generated by this game.
- Rating – The game’s rating (by users).
In this section we’ll focus on using GROUP BY and aggregate functions .
Exercise: Show the average production cost of games that were produced between 2010 and 2015 and were rated higher than 7 .
Explanation: In the SELECT statement, we use the aggregate function AVG() to compute the average production cost. We give ProductionCost as an argument; the full expression is AVG(ProductionCost) .
In the WHERE clause, we filter for high-rated games ( Rating > 7 ) and produced between 2010 and 2015 ( ProductionYear BETWEEN 2010 AND 2015 ).
Exercise: For all games, display how many games were released each year (as the count column ), the average cost of production (as the AvgCost column), and their average revenue (as the AvgRevenue column).
Explanation: You’re used to the basic SELECT syntax, so we won’t go over that. In this query, we are using GROUP BY to organize rows into groups based on a given value. When we do that, we can find statistics for each group.
In the SELECT , we list the ProductionYear and the following expressions:
- COUNT(*) to count rows in each group.
- AVG(ProductionCost) to compute the average production cost in each group.
- AVG(Revenue) to calculate the average revenue for each group.
After FROM , we add the GROUP BY . Since we want to compute statistics for each production year, we use GROUP BY ProductionYear .
Exercise: For each company, select its name, the number of games it produced (as the NumberOfGames column), the average cost of production (as the AvgCost column). Note: Show only the companies that produced more than one game.
Explanation: In this query we select data from the Games table. We select Company , COUNT(*) to count rows for this company, and AVG(ProductionCost) to compute the average production cost for all games produced by this company.
We then use GROUP BY Company to group games produced by each company. Finally, we use the HAVING clause to limit the results to companies that produced more than one game.
Exercise: We're interested in good games produced between 2000 and 2009. A good game is a game that has a rating higher than 6 and was profitable (earned more than its production costs).
For each company, show the company name, its total revenue from good games produced between 2000 and 2009 (as the RevenueSum column), and the number of good games it produced in this period (as the NumberOfGames column). Only show companies with good-game revenue over 4 000 000.
Explanation: In SELECT , we list the Company to get the name of the company, COUNT(*) to count the number of games produced by this company, and SUM(Revenue) to compute the company’s total revenue.
In WHERE , we apply the row-level filters mentioned in the exercise:
- ProductionYear BETWEEN 2000 AND 2009 to find games produced between 2000 and 2009.
- Rating > 6 to find games with rating above 6.
- Revenue - ProductionCost > 0 to find games with more revenue than production costs.
We group the rows using GROUP BY Company . Finally, we use HAVING to find companies with total revenue above 4000000.
Exercise: For all companies present in the table, show their name and the sum of gross profit over all years. To simplify this problem, assume that the gross profit is Revenue - ProductionCost ; show this column as GrossProfitSum .
Make sure the results start with the company that had the highest gross profit.
Explanation: In the SELECT statement, we list the values Company and SUM(Revenue - ProductionCost) . The expression Revenue - ProductionCost computes the gross profit for each game and SUM(Revenue - ProductionCost) sums this profit across multiple games.
We then group the data by company ( GROUP BY Company ), and order the results by the total gross profit in descending order. Finally, we order by gross profit; we specify descending order (10-1 instead of 1-10) so that the highest profit comes first.
You can find more exercises specifically for GROUP BY in 10 GROUP BY SQL Practice Exercises with Solutions
Section 3: The Art of the JOIN
In this section, we’ll focus on JOINs. We’ll work with a database with data about pieces of art. There are three tables in the database.
The table Artist has the following columns:
- Id – The ID of a given artist.
- Name – The artist’s name.
- BirthYear – The year the artist was born.
- DeathYear – The year the artist died.
- ArtisticField – The artist’s preferred field (e.g. painting, sculpture).
The table PieceOfArt has the following columns:
- Id – The ID of a given piece of artwork.
- Name – The work’s name.
- ArtistId – The ID of the artist who created the work.
- MuseumId – The ID of the museum that houses the work.
The table Museum consists of the following three columns:
- Id – The ID of a given museum.
- Name – The museum’s name.
- Country – The country where the museum is located.
Exercise: Show the names of all pieces of art, together with the names of their creators and the names of the museums that house the art.
Do not include lost works (i.e. those without a museum ID) and pieces with an unknown artist. Name the columns PieceOfArtName , ArtistName , and MuseumName .
Explanation: We want to list all pieces of art for which we have complete information (artist, museum). This tells us that we have to use INNER JOIN to join the tables.
We use the JOIN keyword, as its equivalent to INNER JOIN . We first join the tables Museum and PieceOfArt on the museum ID. Then we join the Artist table on the artist ID.
You can read about joining multiple tables in How to Join 3 Tables (or More) in SQL
Exercise: Find artists who lived more than 50 years and were born after the year 1800 . Show their name and the name of the pieces of art they created. Rename these columns ArtistName and PieceName , respectively.
Explanation: Here we join the tables Artist and PieceOfArt on the artist ID. In the WHERE clause, we filter for artists who lived longer than 50 years. We do this by computing the age of the artist with an expression DeathYear - BirthYear and filtering it using the comparison DeathYear - BirthYear > 50 .
We also filter for artists from the 19th century or later with the condition BirthYear > 1800 . We combine the two conditions with an AND operator.
Exercise: Show the names of artists together with the number of years they lived (name the column YearsLived ) and the number of pieces they created (name the column NumberOfCreated ).
Only show artists who created at least one piece of art.
Explanation: This SQL query selects the artist’s name, the number of years they lived ( DeathYear - BirthYear ), and the total number of pieces they created COUNT(Poa.ArtistId) .
The data is joined on the artist ID between the Artist table and the PieceOfArt table. The results are grouped by the artist's name and their lifespan.
Two things are important to note here. First, we have to include the DeathYear - BirthYear expression in the GROUP BY clause, since this expression is unaggregated. Otherwise the database could throw an error. (You can read about the error in How to Fix a 'Not a GROUP BY Expression' Error and How to Solve the Error “must appear in the GROUP BY clause” .)
Second, since we’re using INNER JOIN , we’re already guaranteed to get artists who have created at least one piece of art. Artists with no artwork will be omitted by this JOIN .
You can find more SQL JOIN exercises in SQL Joins: 12 Practice Questions with Detailed Answers
Section 4: A Cart Load of Data
In this final section, we’ll work with data from a store database. It has five tables:
Categories stores the names of product categories:
- Id – The ID of a given category
- Name – The category name.
Products stores product info:
- Id – The ID of a given product.
- Name – The product’s name.
- CategoryId – The ID of the category the product belongs to.
- Price – The product’s price.
Clients stores basic shopper info:
- Id – The ID of a given client.
- FirstName – The client’s first name.
- LastName – The client’s last name.
Orders records basic order info:
- Id – The ID of a given order.
- ClientId – The ID of the client who placed the order.
- Year – The year the order was placed.
Finally, the table OrderItems contains data about which items make up each order. This is an associative table that connects data from the Orders and Products tables. It consists of the following columns:
- OrderId – The ID of the order.
- ProductId – The ID of the product in the above order.
- Quantity – The quantity of the product in this order.
- Price – The total price for the product in this order.
Exercise: For each order, select its ID (name the column OrderId ), the first and last name of the client who placed this order, and the total revenue generated by this order (name the column Revenue ).
Note: The revenue for the order is the sum of the Price column for each item in the order.
Explanation: In this query, we join the tables Orders , OrderItems , and Clients .
In SELECT , we select four expressions: the ID of the order, the first and last name of the client, and the sum of all order item prices. In GROUP BY , we group the data by order ID and the client’s first and last names. This gives us the total revenue for each order with information (first and last names) about the client.
Exercise: Select the first name and last name of the clients who repurchased products (i.e., bought the same product in more than one order). Include the names of those products and the number of the orders they were part of (name the column OrderCount ).
Explanation: Here we join four tables: Clients , Orders , OrderItems , and Products .
In SELECT , we select the first and last name of the client, the name of the product, and the count of orders in which this product was purchased by this client. We group the table by client data (first and last name), and by the product name. This way, purchases by this client of this product are grouped together.
In HAVING , we filter for rows where the count of orders is higher than 1. This lets us select clients who purchased the same product in more than one purchase.
Exercise: Select the first and last name of each client, the name of the category they purchased from (in any of their orders), and the total amount of money they spent on this product category (name this column TotalAmount ).
Solution: We join the tables Categories , Products , OrderItems , Orders , and Clients . We select the first and last name of the client, the name of the category and the sum of order items prices. This allows us to compute how much money each client spent in each category.
We group the results by the first and last name of the client and by the name of the category. This way, all purchase items for each client and each category are grouped together.
I've had quite the experience exploring the diverse world of data with T-SQL. From uncovering the secrets behind cat behaviors to analyzing game strategies and appreciating art through numbers, SQL has been my trusty tool. It's changed the way I look at questions and discover the stories hidden in data around us.
Would you like more SQL Server practice? Check those awesome resources:
- Learning SQL? 12 Ways to Practice SQL Online
- How to Create Your Own Database to Practice SQL
- SQL Server Cheat Sheet
If you're ready to deepen your skills, our SQL Practice Set in MS SQL Server course is just what you need. It's designed to strengthen your foundation and boost your ability to analyze and interpret data effectively. With each exercise, you'll feel more confident and skilled in tackling complex queries.
For those wanting to explore every aspect of SQL, our comprehensive SQL from A to Z in MS SQL Server track covers everything from the basics to advanced techniques. It's a perfect learning path for anyone aiming to master SQL Server and make informed decisions based on data insights. Whether you're a beginner or looking to brush up on your skills, these resources will help you succeed in the world of data.
Don't wait any longer—start mastering SQL Server today and unlock the full potential of your data!
You may also like
How Do You Write a SELECT Statement in SQL?
What Is a Foreign Key in SQL?
Enumerate and Explain All the Basic Elements of an SQL Query
IMAGES
VIDEO