SELECT Statement
Beginner⏱️ 7 mins read
What You'll Learn
SELECT retrieves data from one or more tables. You can select all columns with * or specify individual columns. Aliases (AS) rename a column or table for the duration of the query. SQL execution order: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY — SELECT is processed near the end!
Syntax
SELECT * FROM table_name;
SELECT col1, col2 FROM table_name;
SELECT col1 AS alias FROM table_name;Example
SELECT name, salary * 12 AS annual_salary
FROM employees;
-- Multiple columns with aliases
SELECT
name AS employee,
salary AS monthly_pay,
hire_date
FROM employees;Beyond the Basics
Data in play — reference tables for this topic
-- employees (created in Topic 1)
-- id | name | department_id | salary | hire_date
-- 1 | Ada | 1 | 145000 | 2021-03-01
-- 2 | Grace | 1 | 115000 | 2022-06-13
-- 3 | Alan | 2 | 92000 | 2020-11-02
-- 4 | Edsger | NULL | 78000 | 2023-08-19
-- 5 | Barbara | 3 | 64000 | 2024-01-08SELECT computes — it doesn't just copy
Every item in the SELECT list is an expression evaluated per row, not just a column reference. Arithmetic, string functions, and conditionals all work here — this is where SQL stops being a retrieval language and becomes a calculation engine.
SELECT
name,
salary,
ROUND(salary * 1.10, 2) AS proposed_raise, -- computed per row
salary * 12 AS annual_cost,
EXTRACT(YEAR FROM hire_date) AS hire_year -- Topic 14 expands on dates
FROM employees;Aliases are cosmetic — and invisible to WHERE
AS renames an output column; it does not create a variable. The logical execution order is FROM → WHERE → SELECT → ORDER BY, so an alias defined in SELECT does not exist yet when WHERE runs — the single most common beginner SQL error.
-- Works: ORDER BY runs AFTER SELECT, so the alias exists
SELECT name, salary * 12 AS annual_cost
FROM employees
ORDER BY annual_cost DESC;
-- Fails in most engines: WHERE runs BEFORE SELECT
SELECT name, salary * 12 AS annual_cost
FROM employees
WHERE annual_cost > 1000000; -- ERROR: unknown columnProjection is your first performance habit
SELECT * reads every column, defeats covering indexes (Topic 21), and drags wide TEXT columns across the network for no reason. Naming columns explicitly makes the query self-documenting and gives the engine less work to do.
-- The dashboard only needs two fields — say so:
SELECT name, salary FROM employees;
-- NOT this: also fetches hire_date, department_id, and everything else
-- SELECT * FROM employees;Common Mistakes
Using SELECT * in production fetches ALL columns, increasing I/O and network overhead. Always select only the columns you need. Also, aliases defined in SELECT cannot be used in WHERE (because WHERE runs before SELECT).
Interview Tips
Know the SQL execution order cold — FROM, JOIN, WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, LIMIT. Interviewers frequently ask why you can't use a SELECT alias in a WHERE clause.
Official References
Test Yourself — 7 questions
1. Given: SELECT name, salary * 12 AS annual_cost FROM employees — what is salary * 12?
2. Can the alias annual_cost be used in the WHERE clause of the same query?
3. Can the same alias be used in ORDER BY?
4. What is the logical execution order of the early pipeline stages?
5. Why is SELECT * discouraged in production code?
6. In what practical way does column order in the SELECT list matter?
7. FROM produces rows, WHERE filters them, and SELECT…?
Practice
Return only the name and salary columns for all employees.
⚡ Solve it in the SQL playground →Frequently Asked Questions
Can I ever use an alias in WHERE?
Not portably. Because WHERE runs before SELECT, standard SQL has no alias there. Some engines relax this in GROUP BY or HAVING (MySQL does; PostgreSQL and SQL Server do not). The portable habit: repeat the expression, or compute it in a subquery/CTE (Topics 16-17).
Does the order of columns in the SELECT list matter?
Semantically no — SQL is set-based. Practically yes for clients: column order is what drivers, exports, and SELECT * consumers observe, and it can break positional consumers if it changes.