SQL Basics: Ask Questions of Your Data
SQL is how you ask a database for exactly the data you want. It reads almost like English, and the basics take an afternoon. Learn the core commands and run real queries in the playground on this page.
Tables, rows and columns
A database stores data in tables, a lot like spreadsheet tabs. Each column holds one kind of fact (a name, an age), and each row is one record (one pet, one order, one customer).
SQL (Structured Query Language, said “S-Q-L” or “sequel”) is the language you use to ask a database questions. The same basics work in MySQL, PostgreSQL, SQLite, Microsoft SQL Server and most others, with small differences in the advanced stuff.
All the examples here use this small table called pets, from an imaginary animal shelter:
A query is a question. You don't tell the database how to find the answer, only what you want. “Give me the names of all cats in Austin” becomes one line of SQL.
SELECT: pick your columns
Every query starts with SELECT (which columns) and FROM (which table).
SELECT name, species FROM pets;- List columns with commas between them. The result shows them in that order.
SELECT *means “every column.” Handy for a quick look, but in real work, name the columns you need.- Keywords like
SELECTaren't case-sensitive. Writing them in capitals is a common habit that makes queries easier to read. - End with a semicolon
;. Many tools need it when you run several queries at once.
You can rename a column in the result with AS: SELECT name AS pet_name FROM pets;
WHERE: filter the rows
WHERE keeps only the rows that match a condition.
SELECT name, age FROM pets WHERE species = 'cat';| Write | Means |
|---|---|
= | equals |
<> or != | not equal |
> < >= <= | greater / less than |
AND / OR | both must match / either can match |
LIKE 'B%' | pattern: % = any letters, _ = exactly one |
NOT | flips a condition |
SELECT name, species, age FROM pets
WHERE city = 'Austin' AND age < 5;Text goes in single quotes: 'cat'. Without quotes, SQL thinks cat is a column name. Numbers don't need quotes. Also, in many databases 'Cat' and 'cat' aren't equal, so match the capitals in your data.
Mixing AND with OR? AND is checked first, like multiplication before addition. Use parentheses to be clear: WHERE (species = 'cat' OR species = 'dog') AND age > 8.
ORDER BY and LIMIT
Rows come back in no guaranteed order unless you ask. ORDER BY sorts them: ASC is smallest first (the default), DESC is largest first. LIMIT keeps only the first few rows.
-- the 3 heaviest pets
SELECT name, weight FROM pets
ORDER BY weight DESC
LIMIT 3;- Sort by more than one column with commas:
ORDER BY city, age DESCsorts by city, then by age within each city. - The clauses must go in this order:
SELECT … FROM … WHERE … GROUP BY … ORDER BY … LIMIT. - Lines starting with
--are comments. - SQL Server uses
SELECT TOP 3 …instead ofLIMIT 3.
COUNT, SUM, AVG and GROUP BY
Aggregate functions squash many rows into one number:
| Function | Gives you |
|---|---|
COUNT(*) | how many rows |
SUM(col) | the total |
AVG(col) | the average |
MIN(col) / MAX(col) | the smallest / largest |
SELECT COUNT(*) FROM pets WHERE species = 'dog';GROUP BY splits the rows into groups first, then runs the function once per group. It's how you answer “how many per…” or “average for each…” questions.
SELECT species, COUNT(*) AS how_many, AVG(weight) AS avg_weight
FROM pets
GROUP BY species
ORDER BY how_many DESC;The GROUP BY rule: every column in your SELECT must either be in the GROUP BY or be inside a function like COUNT. Otherwise the database doesn't know which row's value to show for the group. To filter groups after counting, real databases use HAVING, for example HAVING COUNT(*) > 2.
The SQL playground
Type a query about the pets table and press Run (or Ctrl+Enter). Then try the challenges. This playground understands SELECT, FROM, WHERE (with AND, OR, NOT, LIKE and parentheses), GROUP BY, ORDER BY, LIMIT, AS and COUNT/SUM/AVG/MIN/MAX.
The idea behind JOIN
Real databases split data into several tables so nothing is stored twice. Say the shelter also has an adopters table, and each pet row stores an adopter_id:
| name | adopter_id |
|---|---|
| Bella | 1 |
| Luna | 2 |
| Max | 1 |
| Milo |
| id | adopter |
|---|---|
| 1 | Jordan |
| 2 | Priya |
| 3 | Sam |
A JOIN lines up rows from two tables wherever a column matches, here pets.adopter_id = adopters.id:
SELECT pets.name, adopters.adopter
FROM pets
JOIN adopters ON pets.adopter_id = adopters.id;| name | adopter |
|---|---|
| Bella | Jordan |
| Luna | Priya |
| Max | Jordan |
- A plain
JOIN(also calledINNER JOIN) keeps only rows with a match on both sides. Milo has no adopter, and Sam hasn't adopted anyone, so neither appears. LEFT JOINkeeps every row from the first table, with empty values where there's no match. Use it for “all pets, and their adopter if they have one.”- Write
table.columnwhen both tables could have a column with the same name.
Why split tables? If Jordan changes their phone number, you update one row in adopters, not every pet they've adopted. This idea is called normalization.
FAQCommon questions
Where can I practice SQL on my own computer?
SQLite is free, tiny and needs no server. A free app like DB Browser for SQLite lets you open a database file and run queries. For bigger projects, PostgreSQL and MySQL are both free.
Can a SELECT query change my data?
No. SELECT only reads. Commands that change data are INSERT (add rows), UPDATE (change rows) and DELETE (remove rows). Be careful with those: an UPDATE or DELETE without a WHERE changes every row in the table.
What's the difference between COUNT(*) and COUNT(column)?
COUNT(*) counts every row. COUNT(column) counts only rows where that column isn't empty (NULL).
What does NULL mean?
NULL means “no value” or “unknown.” It isn't zero or an empty string. You can't test it with =; use WHERE col IS NULL or IS NOT NULL instead.
Is SQL a programming language?
It's a query language: you describe the result you want, and the database figures out how to get it. It's one of the most useful skills for data analysis, and it pairs well with spreadsheets and Python.