Expressions, Aliases, and Functions
Lora is planning matinee pricing: every afternoon ticket at 20% off. The discounted prices exist nowhere in the database — and they don't need to. A query can compute while it reads: show each screening's stored price and, right next to it, the matinee price derived on the fly, under a readable column name.
That is this page's one idea, worn three ways. An expression is a small computation written where a column name would go. An alias gives the computed column a name worth reading. And functions are the built-in helpers — rounding, changing case, measuring length — that expressions call on. Together they mean queries don't just fetch facts; they derive conclusions from them.
Arithmetic While You Read
In English: show each screening's price, and next to it the price times 0.8. The multiplication sits right in the SELECT list, where a column name would normally be:
SELECT screening_id, price, price * 0.8 FROM screenings;
| screening_id | price | price * 0.8 |
|---|---|---|
| 1 | 12.00 | 9.60 |
| 2 | 10.00 | 8.00 |
| 3 | 12.00 | 9.60 |
| 4 | 9.50 | 7.60 |
The database evaluated price * 0.8 once per row and put the result in the answer. Nothing was stored: the screenings table still holds price and only price. Ask again tomorrow and the matinee numbers are derived again, fresh, from whatever the stored prices are then. A receipt at a till is the right picture — the shelf price is what's stored, and the line total is computed at the till, every time, from the same stored facts. Map the picture, drop it: derived values live in answers, stored values live in tables.
AS Gives It a Name
That third column heading — price * 0.8 — is what the database shows when you don't name a computed column, and no one wants to read it on a schedule board. The keyword AS attaches an alias, a name that exists only in this answer:
SELECT screening_id, price, price * 0.8 AS matinee_price FROM screenings;
| screening_id | price | matinee_price |
|---|---|---|
| 1 | 12.00 | 9.60 |
| 2 | 10.00 | 8.00 |
| 3 | 12.00 | 9.60 |
| 4 | 9.50 | 7.60 |
One honest footnote: in most engines the word AS is optional — price * 0.8 matinee_price works too — but always writing it is kinder to the next reader, and the next reader is usually you. Aliases also rename ordinary columns (runtime_min AS minutes) whenever a report needs friendlier headings.
A Tour of Everyday Functions
A function takes a value in and hands a value back: you write its name, then the input in parentheses. ROUND(9.6, 1) rounds to one decimal place; UPPER(title) and LOWER(email) shift text to one case; LENGTH(title) measures how long a piece of text is (with one engine wrinkle — MySQL counts bytes here, where CHAR_LENGTH gives the character count). Like arithmetic, a function in the SELECT list runs once per row against a copy of the value — the marquee sign needs shouting capitals is one function call away:
SELECT UPPER(title) AS sign_title,
ROUND(runtime_min / 60.0, 1) AS hours
FROM films;
| sign_title | hours |
|---|---|
| THE LONG RAIN | 1.9 |
| PAPER LANTERNS | 1.6 |
| NIGHT BUS | 1.6 |
And to be clear about what did not happen: the films table still says "The Long Rain", in ordinary case. UPPER shouted at a copy in the answer; the stored title never heard it. Functions in a SELECT transform the copy being examined, never the data itself.
Dates get functions too — extract the year from joined_on, subtract two dates to count days — and here comes the engine-honesty sentence: date function names vary annoyingly between engines, so the exact spelling is a thing you look up per engine, while the idea — dates are values you can compute with — is universal.
Functions in WHERE Too
Everything above works in a WHERE clause as well, which resolves last topic's loose end about text case. Lora wants the customers with Gmail addresses, however their emails happen to be capitalized. Lowercase each email before testing it, and match the pattern anything, then @gmail.com:
SELECT name, email FROM customers WHERE LOWER(email) LIKE '%@gmail.com';
Two new things in one line, so read it slowly. LOWER(email) normalizes each row's email to lowercase for the test — the stored emails keep their capitals. And LIKE compares against a pattern instead of an exact value, where % means "anything here": the pattern reads anything, ending in @gmail.com. Consider LIKE a cameo appearance — pattern matching is a deeper toolbox than one page can hold — but the lowercase-before-comparing trick is the everyday standard for case-proof text tests, and it's yours now.
- "The computed column is now in the table." Derived values live in the answer only. The screenings table still holds
priceand nothing else — run the query again and matinee_price is computed again, fresh. - "I should store the discounted price too." Store facts, derive conclusions. Store both and one day they'll disagree — someone updates the price and forgets the discount. This instinct grows into a design principle in Chapter 6.
- "Functions change the data." In SELECT and WHERE, a function transforms the copy being examined.
UPPER(email)shouts at nobody's actual email; the stored value is untouched. - "An alias renames the real column." An alias exists only in that one answer. The table's column is still named what CREATE TABLE named it; the next query starts from scratch.
- Deriving at read time is the everyday power move of SQL: prices with tax, ages from birthdays, names normalized for matching — all computed fresh from stored facts, never stored twice.
- "Store facts, derive conclusions" looks like a syntax lesson and is actually a design principle — it's half of why databases stay trustworthy, and Chapter 6 builds on it by name.
Knowledge Check
After running SELECT price, price * 0.8 AS matinee_price FROM screenings;, what does the screenings table contain?
- Both price and a new matinee_price column
- Just price, exactly as before the query ran
- The price column, overwritten with discounted values
- A price column renamed to matinee_price
What does AS do in price * 0.8 AS matinee_price?
- Permanently renames the price column
- Names the computed column in this answer only
- Performs the multiplication itself
- Saves the expression so future queries can reuse it
Lora runs SELECT UPPER(title) FROM films;. What happens to the title "Night Bus" stored in the table?
- Nothing — the answer shows NIGHT BUS, the table still says Night Bus
- It becomes NIGHT BUS in the stored films table from now on, permanently
- The table keeps both versions side by side
- An error — UPPER only works inside WHERE
Why is "store facts, derive conclusions" better than also storing the matinee price in the table?
- Because tables have a strict limit on column count
- Because computed columns are always faster to read
- Because stored twice, the two values will eventually disagree
- Because SQL flatly forbids storing any value that could be computed instead
You got correct