What is the difference between a table alias and a column alias, and when do I need each one?
A table alias renames the relation for the duration of the query, which matters most when the same table appears twice. A column alias renames the output column of the projection, which matters when the expression is not a plain column or when the raw name is ambiguous.
CREATE TABLE staff (
id INTEGER PRIMARY KEY,
name VARCHAR(120) NOT NULL,
manager_id INTEGER
);
INSERT INTO staff (id, name, manager_id) VALUES
(1, 'Ada Lovelace', NULL),
(2, 'Grace Hopper', 1),
(3, 'Alan Turing', 1),
(4, 'Katherine Johnson', 2);
-- The table alias makes it clear which copy of id is which.
SELECT e.name AS employee, m.name AS manager
FROM staff AS e
JOIN staff AS m ON m.id = e.manager_id
ORDER BY e.name;Three rows come back: Alan Turing managed by Ada Lovelace, Grace Hopper managed by Ada Lovelace, and Katherine Johnson managed by Grace Hopper. Ada Lovelace herself is absent because her manager_id is NULL and an inner join requires a match — the query is asking for employees who have a manager, and she does not.
A table alias is not optional in a self join. With two copies of staff in the FROM clause, an unqualified id is ambiguous and the engine rejects it. The aliases e and m are what make e.manager_id = m.id meaningful.
The visibility rules are the part that trips people up, and they follow the same stage order as the rest of the query. A column alias can be referenced in ORDER BY and in GROUP BY, because both run after the projection. It cannot be referenced in WHERE, because WHERE runs before the projection exists. A table alias, by contrast, is available everywhere the table is, including the WHERE clause.
Some teams skip the AS keyword because it is optional in most engines. Write it anyway: it is clearer, and it avoids the case where an alias starts with a digit or collides with a reserved word and the engine guesses wrong.