Column Aliases
A column alias renames the column header in the result set. It has no effect on the underlying data — it only changes what label appears at the top of that column when the query result is displayed.
-- Without alias: the column header is 'salary * 12' (ugly)
SELECT first_name, salary * 12
FROM employees;
-- With alias: the column header is 'annual_salary' (readable)
SELECT first_name, salary * 12 AS annual_salary
FROM employees;
-- AS is optional — this works too (but AS is recommended for clarity)
SELECT first_name, salary * 12 annual_salary
FROM employees;
-- Rename an existing column in the output
SELECT first_name AS name, department AS dept
FROM employees;
Alice Engineering 1020000
Bob Marketing 744000
Multi-word Aliases
If your alias contains spaces, wrap it in double quotes (standard SQL and PostgreSQL) or backticks (MySQL):
-- Standard SQL / PostgreSQL: use double quotes for multi-word aliases
SELECT salary AS "Monthly Pay", salary * 12 AS "Annual Salary"
FROM employees;
-- MySQL: backticks also work
SELECT salary AS `Monthly Pay`, salary * 12 AS `Annual Salary`
FROM employees;
-- Best practice: use underscore_names to avoid quoting entirely
SELECT salary AS monthly_pay, salary * 12 AS annual_salary
FROM employees;
Multi-word aliases with spaces require quoting every time you reference them, both in SQL and in your application code. Stick to snake_case (underscores) for aliases to keep queries readable without any quoting. Reserve quoted aliases for reports and dashboards where the column header is shown to end users.
Table Aliases
A table alias gives a table a shorter name within the query. This is purely for convenience in simple queries, but becomes essential in joins where you need to prefix column names with the table name to avoid ambiguity.
-- Without table alias (verbose)
SELECT employees.first_name, employees.salary
FROM employees;
-- With table alias — 'e' is the alias for employees
SELECT e.first_name, e.salary
FROM employees e;
-- AS is optional for table aliases too
SELECT e.first_name, e.salary
FROM employees AS e;
-- Useful for long table names
SELECT o.id, o.total, o.order_date
FROM customer_orders AS o
WHERE o.total > 100;
Aliases in Joins – Resolving Ambiguity
Table aliases are not just convenient in joins — they are often required. When two tables have a column with the same name (e.g. both have an id column), the database cannot tell which table you mean without a table prefix. Aliases make this explicit and keep JOIN queries readable.
-- Without aliases: ambiguous — which 'id' is which?
SELECT id, name, total
FROM orders
JOIN customers ON orders.customer_id = customers.id;
-- Error: column 'id' is ambiguous (both tables have it)
-- With aliases: clear and unambiguous
SELECT o.id AS order_id,
c.name AS customer_name,
o.total
FROM orders AS o
JOIN customers AS c ON o.customer_id = c.id;
-- Three-table join — aliases keep it manageable
SELECT
o.id AS order_id,
c.name AS customer_name,
p.name AS product_name,
oi.quantity,
oi.unit_price
FROM orders AS o
JOIN customers AS c ON o.customer_id = c.id
JOIN order_items AS oi ON oi.order_id = o.id
JOIN products AS p ON oi.product_id = p.id
WHERE o.total > 500;
In simple queries, single-letter aliases (e for employees, o for orders, c for customers) are widely used. For complex queries with many joins, slightly longer abbreviations (emp, ord, cust) can be clearer. Avoid overly long aliases — they defeat the purpose of shortening the code.
Alias Scope Rules
Column aliases defined in SELECT can only be used in certain clauses — not everywhere. Understanding this prevents a common category of SQL errors:
| Clause | Can use column alias? | Reason |
|---|---|---|
| WHERE | No | WHERE runs before SELECT — alias not yet defined |
| GROUP BY | Sometimes (MySQL yes, PostgreSQL no) | Varies by database dialect |
| HAVING | Sometimes (MySQL yes, PostgreSQL no) | Varies by database dialect |
| ORDER BY | Yes — all databases | ORDER BY runs after SELECT |
-- WRONG: cannot use alias in WHERE (runs before SELECT)
SELECT salary * 12 AS annual_salary
FROM employees
WHERE annual_salary > 900000; -- Error in PostgreSQL / SQL Server
-- CORRECT: repeat the expression in WHERE
SELECT salary * 12 AS annual_salary
FROM employees
WHERE salary * 12 > 900000;
-- CORRECT: use a subquery or CTE to reference alias in WHERE
SELECT *
FROM (
SELECT first_name, salary * 12 AS annual_salary
FROM employees
) AS derived
WHERE annual_salary > 900000;
-- CORRECT: alias IS usable in ORDER BY (all databases)
SELECT first_name, salary * 12 AS annual_salary
FROM employees
ORDER BY annual_salary DESC; -- works everywhere
📋 Summary
- Column alias:
SELECT expression AS alias_name— renames the column header in the output.ASis optional but recommended. - Use double quotes (PostgreSQL) or backticks (MySQL) for multi-word aliases. Prefer
snake_caseto avoid quoting. - Table alias:
FROM table_name AS t— shortens the table reference within the query. - Table aliases are essential in joins to resolve ambiguous column names (e.g. both tables have an
idcolumn). - Column aliases are available in ORDER BY but not in WHERE (WHERE runs before SELECT). Repeat the expression in WHERE, or use a subquery.
FAQ
No — AS is optional in both column and table aliases. SELECT salary * 12 annual_salary and SELECT salary * 12 AS annual_salary are identical. However, always using AS is strongly recommended for readability. It makes the alias explicit and prevents confusion between a missing comma and an accidental alias (e.g. SELECT first_name last_name selects only first_name and aliases it last_name, rather than selecting two columns — a subtle bug).
No — you cannot reference a column alias defined earlier in the same SELECT list. Each expression in SELECT is evaluated independently. For example, SELECT salary * 12 AS annual, annual / 12 AS monthly will fail because annual is not yet a known column when annual / 12 is evaluated. Repeat the expression: SELECT salary * 12 AS annual, salary AS monthly.
No — aliases are temporary and exist only within the scope of the single query. The underlying table and column names are completely unchanged. An alias defined in one query has no effect on any other query, and it is never stored in the database. It is purely a presentation-layer label applied to the result set.
It depends on the database. MySQL and MariaDB allow using column aliases in GROUP BY. PostgreSQL and SQL Server do not — they require you to repeat the expression. Standard SQL (and the safest portable approach) is to repeat the expression: SELECT YEAR(order_date) AS year, COUNT(*) FROM orders GROUP BY YEAR(order_date). Alternatively, wrap the query in a subquery and GROUP BY the alias in the outer query.