Learning SQL
A Step-by-Step Student Guide
Based on the W3Schools SQL Tutorial
[Link]
How to use this guide
This guide walks you through the W3Schools SQL tutorial in a structured order, grouped by skill level.
Each section tells you exactly which pages to visit, what to read, and includes practice exercises to test
yourself.
Work through the phases in order — each one builds on the last.
Use the checklist on the next page to track your progress.
Phase 1 Foundation Phase 2 Filtering & Phase 3 Aggregation Phase 4 Joins &
Sorting Advanced
Progress Checklist
Tick off each topic as you complete it on W3Schools. The colour of each row shows which phase it belongs
to.
# Topic (W3Schools Page) Key Skill Done ✓
1 SQL Introduction What SQL is & does Foundation
2 SQL Syntax Statement structure Foundation
3 SQL SELECT Retrieving columns Foundation
4 SQL SELECT DISTINCT Removing duplicates Foundation
5 SQL WHERE Filtering rows Filtering
6 SQL ORDER BY Sorting results Filtering
7 SQL AND, OR, NOT Combining conditions Filtering
8 SQL INSERT INTO Adding rows Foundation
9 SQL NULL Values Handling missing data Filtering
10 SQL UPDATE Editing rows Foundation
11 SQL DELETE Removing rows Foundation
12 SQL SELECT TOP / LIMIT Returning a subset Filtering
13 SQL LIKE Pattern matching Filtering
14 SQL Wildcards % and _ patterns Filtering
15 SQL IN Matching a list Filtering
16 SQL BETWEEN Range filtering Filtering
17 SQL Aliases Renaming columns/tables Filtering
18 SQL COUNT, AVG, SUM Aggregate functions Aggregation
19 SQL MIN and MAX Extremes Aggregation
20 SQL GROUP BY Grouping rows Aggregation
21 SQL HAVING Filtering groups Aggregation
22 SQL INNER JOIN Matching rows in two Joins
tables
23 SQL LEFT JOIN All left + matched right Joins
24 SQL RIGHT JOIN All right + matched left Joins
25 SQL FULL OUTER JOIN All rows from both tables Joins
26 SQL Self JOIN Table joined to itself Joins
27 SQL UNION Combining result sets Joins
28 SQL EXISTS Subquery existence check Advanced
29 SQL ANY, ALL Subquery comparisons Advanced
30 SQL CASE Conditional logic in SQL Advanced
31 SQL CREATE TABLE Defining a table Advanced
32 SQL DROP TABLE Deleting a table Advanced
33 SQL ALTER TABLE Modifying table structure Advanced
34 SQL CREATE INDEX Speeding up queries Advanced
Phase 1: Foundation — Reading Data
These are the first pages to read on W3Schools. By the end of Phase 1 you will be able to open a database,
see what is in it, add new rows, update existing rows, and delete rows.
Step 1 – SQL Introduction & Syntax
W3Schools pages: SQL Introduction → SQL Syntax
SQL (Structured Query Language) is how you talk to a database. Every instruction you write is called a query.
Queries tell the database what to do — fetch data, add a row, change a value, delete a record.
What you need to know from these pages
SQL stands for Structured Query Language.
SQL is not case-sensitive: SELECT = select = Select. Convention is UPPERCASE for keywords.
Most databases use a semicolon ( ; ) to end each statement.
W3Schools uses a sample database called 'Northwind' throughout the tutorial — learn its tables.
Step 2 – SELECT and SELECT DISTINCT
W3Schools pages: SQL SELECT → SQL SELECT DISTINCT
SELECT is the most-used SQL statement. It retrieves data from one or more columns in a table.
-- Get all columns from the Customers table
SELECT * FROM Customers;
-- Get only specific columns
SELECT CustomerName, Country FROM Customers;
-- Remove duplicates with DISTINCT
SELECT DISTINCT Country FROM Customers;
Try it yourself on W3Schools:
1. Write a query to select all columns from the Products table.
2. Write a query to select only ProductName and Price from Products.
3. How many distinct countries appear in the Customers table? Use SELECT DISTINCT to find out.
Step 3 – INSERT, UPDATE, DELETE
W3Schools pages: SQL INSERT INTO → SQL UPDATE → SQL DELETE
These three statements change the data in a table. Read each page carefully — especially the warnings
about UPDATE and DELETE without a WHERE clause.
-- Add a new row
INSERT INTO Customers (CustomerName, Country)
VALUES ('Acme Corp', 'Kenya');
-- Change existing data
UPDATE Customers
SET Country = 'Uganda'
WHERE CustomerID = 5;
-- Remove a row
DELETE FROM Customers
WHERE CustomerID = 5;
WARNING — always use WHERE with UPDATE and DELETE
Without a WHERE clause, UPDATE changes EVERY row in the table.
Without a WHERE clause, DELETE removes EVERY row in the table.
Always double-check your WHERE condition before running these statements.
Try it yourself:
1. Insert a new customer with your own name and country.
2. Update that customer's city to 'Nairobi'.
3. Delete the customer you just created.
4. What happens if you run DELETE FROM Customers; with no WHERE clause? (Don't actually run it
— just explain.)
Phase 2: Filtering & Sorting
Phase 2 is about narrowing down results. You will learn how to filter rows with WHERE, sort them with
ORDER BY, and match patterns with LIKE and wildcards.
Step 4 – WHERE, AND / OR / NOT
W3Schools pages: SQL WHERE → SQL AND, OR, NOT
WHERE filters which rows come back. AND, OR, and NOT let you combine multiple conditions.
-- Simple filter
SELECT * FROM Customers
WHERE Country = 'Germany';
-- Multiple conditions
SELECT * FROM Customers
WHERE Country = 'Germany' AND City = 'Berlin';
-- Either condition
SELECT * FROM Products
WHERE Price < 10 OR CategoryID = 1;
-- Exclude a value
SELECT * FROM Customers
WHERE NOT Country = 'France';
Step 5 – ORDER BY
W3Schools page: SQL ORDER BY
-- Sort ascending (A to Z, lowest to highest)
SELECT * FROM Products
ORDER BY Price ASC;
-- Sort descending (highest to lowest)
SELECT * FROM Products
ORDER BY Price DESC;
-- Sort by multiple columns
SELECT * FROM Customers
ORDER BY Country ASC, CustomerName ASC;
Step 6 – LIKE, Wildcards, IN, BETWEEN
W3Schools pages: SQL LIKE → SQL Wildcards → SQL IN → SQL BETWEEN
The two main wildcards
% (percent) — matches any sequence of characters. 'A%' matches anything starting with A.
_ (underscore) — matches exactly one character. '_ohn' matches 'John', 'Bohn', etc.
-- Names starting with 'A'
SELECT * FROM Customers WHERE CustomerName LIKE 'A%';
-- Names ending with 'son'
SELECT * FROM Customers WHERE CustomerName LIKE '%son';
-- Match a list of values
SELECT * FROM Customers
WHERE Country IN ('Germany', 'France', 'UK');
-- Match a range
SELECT * FROM Products
WHERE Price BETWEEN 10 AND 20;
Filtering challenge — write queries to answer these questions:
1. Find all products with a price greater than 50.
2. Find all customers in the UK or USA.
3. Find all customers whose name contains the word 'Island'.
4. Find all orders placed between 1997-01-01 and 1997-06-30.
5. Find all customers NOT in Germany.
Bonus: Combine two or more conditions in a single query.
Step 7 – NULL Values & Aliases
W3Schools pages: SQL NULL Values → SQL Aliases
NULL means 'no value'. You cannot use = NULL in a WHERE clause — you must use IS NULL or IS NOT NULL.
-- Find rows with no value in Address
SELECT * FROM Customers WHERE Address IS NULL;
-- Find rows that do have an address
SELECT * FROM Customers WHERE Address IS NOT NULL;
-- Rename a column in the result
SELECT CustomerName AS Name, Country AS Location
FROM Customers;
Phase 3: Aggregation — Summarising Data
Aggregation is where SQL gets powerful for data analysis. Instead of returning individual rows, aggregate
functions summarise many rows into a single number.
Step 8 – COUNT, SUM, AVG, MIN, MAX
W3Schools pages: SQL COUNT, AVG, SUM → SQL MIN and MAX
The five aggregate functions
COUNT(*) — how many rows are there?
SUM(column) — add up all values in a column
AVG(column) — average value
MIN(column) — smallest value
MAX(column) — largest value
-- How many customers are there?
SELECT COUNT(*) FROM Customers;
-- Total value of all orders
SELECT SUM(Amount) FROM Orders;
-- Average product price
SELECT AVG(Price) FROM Products;
-- Most expensive and cheapest product
SELECT MAX(Price), MIN(Price) FROM Products;
Step 9 – GROUP BY and HAVING
W3Schools pages: SQL GROUP BY → SQL HAVING
GROUP BY splits rows into groups before applying an aggregate function. HAVING then filters those groups
(like WHERE, but for groups).
-- Count customers per country
SELECT Country, COUNT(*) AS NumberOfCustomers
FROM Customers
GROUP BY Country;
-- Countries with more than 5 customers
SELECT Country, COUNT(*) AS NumberOfCustomers
FROM Customers
GROUP BY Country
HAVING COUNT(*) > 5;
-- Average price per category, only show > 20
SELECT CategoryID, AVG(Price) AS AvgPrice
FROM Products
GROUP BY CategoryID
HAVING AVG(Price) > 20;
WHERE vs HAVING — the key difference
WHERE — filters individual rows BEFORE grouping. Cannot use aggregate functions.
HAVING — filters groups AFTER aggregation. Can use aggregate functions.
Rule of thumb: if your condition involves COUNT / SUM / AVG / MIN / MAX, use HAVING.
Aggregation challenge:
1. How many products are in the Products table?
2. What is the average price of all products?
3. List each country and how many customers it has. Sort by count descending.
4. Find categories where the average product price is above 30.
5. What is the highest-priced product in each category?
Phase 4: Joins — Combining Tables
A JOIN lets you combine rows from two or more tables based on a related column. This is the heart of
relational databases.
Step 10 – INNER JOIN
W3Schools page: SQL INNER JOIN
INNER JOIN returns only the rows where there is a match in BOTH tables.
-- Get orders with customer names
SELECT [Link], [Link]
FROM Orders
INNER JOIN Customers
ON [Link] = [Link];
Step 11 – LEFT, RIGHT, and FULL OUTER JOIN
W3Schools pages: SQL LEFT JOIN → SQL RIGHT JOIN → SQL FULL OUTER JOIN
Join types at a glance
INNER JOIN — only matching rows from both tables
LEFT JOIN — all rows from the LEFT table, plus matches from the right (NULLs where no match)
RIGHT JOIN — all rows from the RIGHT table, plus matches from the left (NULLs where no match)
FULL OUTER JOIN — all rows from both tables (NULLs where no match on either side)
-- All customers, even those with no orders
SELECT [Link], [Link]
FROM Customers
LEFT JOIN Orders
ON [Link] = [Link];
Joins challenge:
1. List all orders with the customer name and employee name for each.
2. Find customers who have NEVER placed an order (hint: use LEFT JOIN + IS NULL).
3. List each product with its category name (join Products to Categories).
4. How many orders has each customer placed? Show customers with 0 orders too.
Step 12 – UNION
W3Schools page: SQL UNION
UNION stacks two SELECT results on top of each other. Both queries must have the same number of
columns and compatible data types. UNION removes duplicates; UNION ALL keeps them.
-- Combine city lists from two tables
SELECT City FROM Customers
UNION
SELECT City FROM Suppliers
ORDER BY City;
Phase 5: Advanced Topics
These topics appear later in the W3Schools tutorial. Work through them after you are comfortable with
Phases 1–4.
Step 13 – CASE (Conditional Logic)
W3Schools page: SQL CASE
CASE lets you return different values based on conditions — like an IF/ELSE inside a query.
SELECT ProductName, Price,
CASE
WHEN Price < 10 THEN 'Budget'
WHEN Price BETWEEN 10 AND 50 THEN 'Mid-range'
ELSE 'Premium'
END AS PriceCategory
FROM Products;
Step 14 – CREATE, DROP, ALTER TABLE
W3Schools pages: SQL CREATE TABLE → SQL DROP TABLE → SQL ALTER TABLE
These are Data Definition Language (DDL) statements — they change the structure of the database rather
than the data inside it.
-- Create a new table
CREATE TABLE Students (
StudentID INT PRIMARY KEY,
Name VARCHAR(100),
EnrolmentDate DATE
);
-- Add a new column
ALTER TABLE Students ADD Email VARCHAR(255);
-- Delete the table entirely
DROP TABLE Students;
Step 15 – EXISTS and Subqueries
W3Schools page: SQL EXISTS
A subquery is a query nested inside another query. EXISTS checks whether a subquery returns any results at
all.
-- Find suppliers who have at least one product under 20
SELECT SupplierName FROM Suppliers
WHERE EXISTS (
SELECT 1 FROM Products
WHERE [Link] = [Link]
AND Price < 20
);
Advanced challenge:
1. Add a 'price tier' label (Budget / Mid-range / Premium) to the Products table using CASE.
2. Create a table called 'Projects' with at least 4 columns of your choice.
3. Find all customers who have placed more than 5 orders using a subquery.
Quick Reference & Study Tips
SQL Statement Order
SQL clauses must always appear in this order when you write a SELECT query:
Correct clause order
SELECT — which columns to return
FROM — which table
JOIN — combine with another table (optional)
WHERE — filter rows (before grouping)
GROUP BY — group rows
HAVING — filter groups (after grouping)
ORDER BY — sort the result
LIMIT — how many rows to return
Common Mistakes to Avoid
• Using = NULL instead of IS NULL in a WHERE clause.
• Forgetting WHERE on an UPDATE or DELETE — this changes/removes every row.
• Putting a column alias in the WHERE clause — SQL processes WHERE before SELECT.
• Confusing WHERE (filters rows) with HAVING (filters groups).
• Using UNION when you need UNION ALL — UNION quietly removes duplicates.
How to Practice
Three ways to practice SQL on W3Schools
1. Try It Yourself — every W3Schools SQL page has a live editor. Run the examples, then modify them.
2. SQL Exercises — go to [Link] for topic-by-topic exercises.
3. SQL Quiz — test your knowledge at [Link]
Suggested Study Schedule
Session Cover Goal
Session 1 Phase 1: Steps 1–3 (Intro, SELECT, Read and run all examples
INSERT/UPDATE/DELETE)
Session 2 Phase 2: Steps 4–6 (WHERE, ORDER BY, LIKE, IN, Complete all filtering exercises
BETWEEN)
Session 3 Phase 2: Step 7 + Phase 3: Steps 8–9 (NULL, Aliases, Write 5 GROUP BY queries
Aggregation)
Session 4 Phase 4: Steps 10–12 (All JOINs, UNION) Draw the join diagrams from
memory
Session 5 Phase 5: Steps 13–15 (CASE, DDL, EXISTS) Complete the W3Schools SQL
Quiz
Session 6 Full revision + W3Schools Exercises Score 80%+ on all exercises