SELECT and Column Aliasing
Pull specific columns from a raw table and rename them to clean, model-ready names.
Why a DE almost never ships SELECT *
When a raw table lands in the warehouse, its columns are named whatever the source system chose: ord_id, cust_nm, amt_c. Those names are cryptic, and they can change without warning. The first transform a data engineer writes, the staging model, selects only the columns downstream needs and renames each to a clean, predictable convention (usually snake_case).
SELECT * is the opposite of that discipline. It drags every column downstream, silently gains a column the moment the source adds one, and hides which fields your model actually depends on. Explicit projection is a contract: it documents exactly what you consume and insulates you from upstream churn. That is why the Apply and Practice exercises ask you to name each column and drop the ones a mart does not need (ord_status, internal_flag).
What SELECT and AS actually do
SELECT is the projection operator: it chooses which columns come back and in what order. It works row by row and never changes how many rows you get. Filtering rows is WHERE's job; setting the grain is GROUP BY's job. Projection only reshapes the columns.
AS renames a column in the output. The alias becomes the output column's name, independent of what the source called it. Downstream models bind to your stable alias, not the source's cryptic identifier.
SELECT
ord_id AS order_id,
cust_id AS customer_id,
amt_c AS amount_cents
FROM orders;
Against the seed rows, that returns:
order_id | customer_id | amount_cents
1001 | 7 | 4999
1002 | 7 | 1250
1003 | 9 | 10000
Three input columns become three cleanly named output columns. ord_status is simply not projected, so it never reaches downstream. Note the amounts are in cents (4999 is 49.99), which is exactly why the alias amount_cents is worth writing: it encodes the unit for whoever reads the model next.
Pitfall: a missing comma silently drops a column
AS is optional in SQL. ord_id order_id means the same as ord_id AS order_id. That convenience is a trap. If you forget a comma between two columns, the query still runs:
SELECT ord_id cust_id FROM orders; -- one column named cust_id, holding ord_id values
SQLite reads cust_id as the alias of ord_id, so you get a single column named cust_id full of order-id values, and no error. The fix is a comma between every projected column. When a projection returns fewer columns than you expected, a swallowed comma is the first thing to check.
Interview nuance: SQL's written order is not its execution order. The engine logically evaluates FROM and WHERE before it projects the SELECT list, so a SELECT-list alias is not yet visible in the same query's WHERE clause. In the SQL standard, and in PostgreSQL, MySQL, and SQL Server, SELECT amt_c AS amount_cents FROM orders WHERE amount_cents > 2000 fails there with an unknown-column error. SQLite, the engine behind this lesson, is unusually lenient and resolves the alias anyway, so that exact query happens to run here. The portable habit is to filter on the real column, WHERE amt_c > 2000. Interviewers ask about alias-in-WHERE to check that you understand logical query order, and that engines differ on it.
CREATE TABLE orders (
ord_id INTEGER,
cust_id INTEGER,
ord_status TEXT,
amt_c INTEGER
);
INSERT INTO orders (ord_id, cust_id, ord_status, amt_c) VALUES
(1001, 7, 'paid', 4999),
(1002, 7, 'shipped', 1250),
(1003, 9, 'paid', 10000);SELECT
ord_id AS order_id,
cust_id AS customer_id,
amt_c AS amount_cents
FROM orders;Apply
Your turn
The task this lesson builds to.
Project three columns from orders and alias them to clean snake_case model names:
ord_id→order_idcust_id→customer_idamt_c→amount_cents
Do not include ord_status.
4 hints and 1 automated check are waiting in the workspace.
Practice
Make it stick
A second problem on the same idea, so it survives past today.
You're standing up the stg_orders staging model, and every downstream mart depends on it exposing clean, renamed columns. Write a query over orders_raw that returns six columns, each raw column renamed to the warehouse alias below and kept in exactly this order; drop internal_flag:
| raw column | output alias |
|---|---|
ord_id | order_id |
cust_id | customer_id |
ord_status | order_status |
amt_c | amount_cents |
ship_region | region |
ord_ts | ordered_at |
3 hints and 1 automated check are waiting in the workspace.