SELECT Statement
Reviewed & published by Brayan K
The SQL SELECT statement retrieves rows from one or more database tables, letting you choose exactly which columns and records you want returned.
Part of the free SQL course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
By the end of this lesson you'll be able to pull exactly the data you want out of any table — choosing columns, renaming them, removing duplicates, paginating, and calculating new values on the fly. SELECT is the command you'll use more than any other in SQL.
What You'll Learn
- Select all columns vs. just the ones you need
- Rename columns in the output with AS
- Remove duplicate rows with DISTINCT
- Page through results with LIMIT and OFFSET
- Build calculated columns with maths
- Read a query result like a database does
Our Sample Table: products
Every query in this lesson runs against this little products table. Keep it in mind as you read — knowing the data is half of writing good SQL.
1. The Basic SELECT
A SELECT statement answers the question "show me some data". The simplest version asks for everything:
SELECT is like ordering from a menu. SELECT * means "bring me one of everything"; SELECT product_name, price means "just the dish name and the price, please".
-- The table this lesson uses:
CREATE TABLE products (
id INTEGER PRIMARY KEY,
product_name TEXT,
category TEXT,
price REAL,
stock INTEGER
);
INSERT INTO products (id, product_name, category, price, stock) VALUES
(1, 'Wireless Mouse', 'Electronics', 24.99, 120),
(2, 'Coffee Mug', 'Kitchen', 9.50, 300),
(3, 'Mechanical Keyboard', 'Electronics', 79.00, 45),
(4, 'Notebook', 'Stationery', 3.25, 500),
(5, 'Desk Lamp', 'Home', 32.00, 80),
(6, 'USB-C Cable', 'Electronics', 12.99, 200);
-- Return EVERY column for EVERY row in the table
SELECT * FROM products;
-- The * is a wildcard meaning "all columns".
-- Great for exploring, but name your columns in real apps (see below).
-- ✅ Expected result:
-- id | product_name | category | price | stock
-- 1 | Wireless Mouse | Electronics | 24.99 | 120
-- 2 | Coffee Mug | Kitchen | 9.5 | 300
-- 3 | Mechanical Keyboard | Electronics | 79 | 45
-- 4 | Notebook | Stationery | 3.25 | 500
-- 5 | Desk Lamp | Home | 32 | 80
-- 6 | USB-C Cable | Electronics | 12.99 | 200In real applications, name the columns you want instead of using * — it's faster, clearer, and won't silently change when the table gains new columns.
-- Uses the products table from the first example.
-- Ask for only the columns you actually need
SELECT product_name, price
FROM products;
-- Cleaner output, faster query, and it won't break
-- if someone adds new columns to the table later.
-- ✅ Expected result:
-- product_name | price
-- Wireless Mouse | 24.99
-- Coffee Mug | 9.5
-- Mechanical Keyboard | 79
-- Notebook | 3.25
-- Desk Lamp | 32
-- USB-C Cable | 12.99Your Turn: pick the columns
Fill in the blanks to list the category and stock of every product. The expected result is in the comments so you can check yourself.
-- Uses the products table from the first example.
-- 🎯 YOUR TURN — fill in the two blanks, then press "Try it Yourself"
-- Goal: list the category and stock level of every product.
SELECT ___, ___ -- 👉 put the column names here: category, stock
FROM products;
-- ✅ Expected result: 6 rows, two columns (category, stock),
-- e.g. Electronics | 120 , Kitchen | 300 , ...2. Renaming Columns with AS
The AS keyword gives a column a friendly name in the result. The underlying table is never changed — the alias only exists for this one query. It becomes essential the moment you start calculating columns.
-- Uses the products table from the first example.
-- AS renames a column just for this result (the table is unchanged)
SELECT
product_name AS "Product",
price AS "Price (USD)"
FROM products;
-- Aliases make headings readable and are essential
-- once you start using calculated columns.
-- ✅ Expected result:
-- Product | Price (USD)
-- Wireless Mouse | 24.99
-- Coffee Mug | 9.5
-- Mechanical Keyboard | 79
-- Notebook | 3.25
-- Desk Lamp | 32
-- USB-C Cable | 12.993. DISTINCT — Remove Duplicates
DISTINCT collapses duplicate rows into one. Our table has three Electronics products, but asking for distinct categories returns each category only once.
-- Uses the products table from the first example.
-- DISTINCT removes duplicate rows from the result
SELECT DISTINCT category
FROM products;
-- A row counts as a duplicate only if EVERY selected
-- column matches, so DISTINCT works on the whole row.
-- ✅ Expected output:
-- category
-- Electronics
-- Kitchen
-- Stationery
-- Home
-- ✅ Expected result:
-- category
-- Electronics
-- Kitchen
-- Stationery
-- HomeYour Turn: unique categories
One blank this time — add the keyword that removes duplicates.
-- Uses the products table from the first example.
-- 🎯 YOUR TURN — fill in the blank to list each category only once.
SELECT ___ category -- 👉 the keyword that removes duplicates
FROM products;
-- ✅ Expected result (4 rows): Electronics, Kitchen, Stationery, Home4. LIMIT & OFFSET — Control How Many Rows
LIMIT caps the number of rows returned; OFFSET skips rows first. Together they power "page 1, page 2, page 3" pagination you see on every website.
LIMIT 3 OFFSET 3 is "skip the first 3 results, then give me the next 3" — exactly page 2 of a 3-per-page list.
-- Uses the products table from the first example.
-- LIMIT caps how many rows come back
SELECT product_name, price
FROM products
LIMIT 3;
-- OFFSET skips rows first — this is how pagination works:
SELECT product_name, price
FROM products
LIMIT 3 OFFSET 3; -- skip the first 3, return the next 3
-- Two queries, so the panel below shows the LAST result — page 2.
-- (Run the first one on its own and you get rows 1-3: Wireless Mouse,
-- Coffee Mug, Mechanical Keyboard.)
-- ✅ Expected result:
-- product_name | price
-- Notebook | 3.25
-- Desk Lamp | 32
-- USB-C Cable | 12.995. Calculated Columns
A SELECT can compute brand-new columns from existing ones using maths or functions. The original data stays untouched — the new column lives only in the result.
-- Uses the products table from the first example.
-- You can compute new columns on the fly
SELECT
product_name,
price,
price * 1.20 AS price_with_tax -- add 20% tax
FROM products;
-- The products table is never changed — the calculation
-- only exists in this query's result.
-- Those trailing digits on the first row are not a bug: 24.99 * 1.20
-- cannot be stored exactly in binary floating point. Real apps wrap the
-- maths in ROUND(price * 1.20, 2) — you'll meet ROUND later in the course.
-- ✅ Expected result:
-- product_name | price | price_with_tax
-- Wireless Mouse | 24.99 | 29.987999999999996
-- Coffee Mug | 9.5 | 11.4
-- Mechanical Keyboard | 79 | 94.8
-- Notebook | 3.25 | 3.9
-- Desk Lamp | 32 | 38.4
-- USB-C Cable | 12.99 | 15.588Common Errors (and the fix)
- "no such column: productname" — column names must match exactly (and SQL has no spaces in names). It's product_name, not productname or "product name".
- Forgetting FROM: SELECT product_name; errors — every column query needs a table: SELECT product_name FROM products;
- SELECT * in real apps: it works, but fetches columns you don't need and breaks code when the table changes. Name your columns.
- Quotes mix-up: use single quotes for text values ('Electronics'); double quotes are for identifiers/aliases in most databases. ' ≠ ".
- Missing semicolon: most tools need ; to end a statement, especially when running several at once.
Frequently Asked Questions
Q: Does the order of columns in SELECT matter?
Yes — the result shows columns in the exact order you list them. SELECT price, product_name puts price first.
Q: Is SQL case-sensitive?
Keywords (SELECT, FROM) are not — but it's convention to UPPERCASE them. Table and column names can be case-sensitive depending on the database, so match them exactly.
Q: Why use AS if the table doesn't change?
Readability and necessity: calculated columns have no name until you give them one, and clear headings make results far easier to read.
Q: Will DISTINCT change my data?
No. SELECT only reads — it never modifies the table. DISTINCT just de-duplicates the result.
Mini-Challenge: Half-Price Preview
Put it all together — a brief, a blank canvas, and the expected result in the comments. Write it, then copy it into a playground to confirm.
-- Uses the products table from the first example.
-- 🎯 MINI-CHALLENGE
-- Using ONLY what this lesson covered (SELECT, AS, calculated columns, LIMIT):
-- 1. Show product_name and a column called half_price (price * 0.5)
-- 2. Return just the first 4 products
--
-- ✅ Expected: 4 rows, columns product_name and half_price
-- e.g. Wireless Mouse | 12.495 , Coffee Mug | 4.75 , ...
-- your query here🎉 Lesson Complete
- ✅ SELECT * grabs everything; naming columns is better in real apps
- ✅ AS renames columns in the output only
- ✅ DISTINCT removes duplicate rows from the result
- ✅ LIMIT + OFFSET cap and paginate results
- ✅ You can compute calculated columns without changing the table
- ✅ Next: the WHERE clause — return only the rows that match a condition
Practice quiz
What does the * wildcard mean in SELECT * FROM products;?
- The first column only
- All rows where a value is true
- All columns
- A calculated column
Answer: All columns. The * is a wildcard meaning 'all columns', so SELECT * returns every column.
What is the purpose of the AS keyword in a SELECT?
- It renames a column only in the query's output
- It permanently renames the column in the table
- It removes duplicate rows
- It sorts the result
Answer: It renames a column only in the query's output. AS gives a column an alias for the result only; the underlying table is unchanged.
What does SELECT DISTINCT category FROM products; return?
- Every category value, with duplicates
- The number of categories
- Only the first category
- Each distinct category value, once
Answer: Each distinct category value, once. DISTINCT collapses duplicate rows so each category appears only once.
What does LIMIT 3 do?
- Skips the first 3 rows
- Returns at most 3 rows
- Returns exactly 3 columns
- Sorts into 3 groups
Answer: Returns at most 3 rows. LIMIT caps the number of rows returned to at most the given number.
Which clause skips rows before returning results, used for pagination?
- OFFSET
- DISTINCT
- AS
- LIMIT only
Answer: OFFSET. OFFSET skips a number of rows first; combined with LIMIT it powers pagination.
In standard SQL, what surrounds a text value such as Electronics in a query?
- Double quotes
- Backticks
- Single quotes
- No quotes
Answer: Single quotes. Text/string literals are written in single quotes, e.g. 'Electronics'. Double quotes are for identifiers.
Does a calculated column like price * 1.20 AS price_with_tax change the table?
- Yes, it updates every row
- No, it only exists in the query result
- Yes, but only the price column
- It deletes the original column
Answer: No, it only exists in the query result. Calculated columns live only in the result; SELECT never modifies the table.
Which query correctly asks for only product_name and price?
- SELECT product_name price FROM products;
- SELECT (product_name, price) products;
- FROM products SELECT product_name, price;
- SELECT product_name, price FROM products;
Answer: SELECT product_name, price FROM products;. List the columns after SELECT separated by a comma, then the table after FROM.
Does the order of columns listed in SELECT affect the result?
- No, columns always come back alphabetically
- Yes, columns appear in the order you list them
- No, order is random
- Only if you use AS
Answer: Yes, columns appear in the order you list them. The result shows columns in the exact order you list them in the SELECT.
On which part of the data does DISTINCT decide a row is a duplicate?
- Only the first selected column
- The id column only
- Every selected column together
- Nothing — it removes random rows
Answer: Every selected column together. A row counts as a duplicate only if every selected column matches; DISTINCT works on the whole selected row.
Continue this course
- Previous: Database Basics & Tables
- Next: WHERE Clause & Filtering — Filter rows by conditions using WHERE, AND, OR, and comparison operators
- Quick reference: SQL cheat sheet › Querying Data