SQL Kitchen

Lesson · Recipe № 013

CTEs

Lesson 13
Recipe

CTEs


WITH names a query before you use it. A common table expression (CTE) runs first, gets a name, and can then be selected from just like a real table, anywhere later in the same statement.

Query

WITH station_avgs AS (
  SELECT station, AVG(price) AS avg_price
  FROM dishes
  GROUP BY station
)
SELECT station, avg_price
FROM station_avgs
WHERE avg_price > 12
ORDER BY avg_price DESC;

↓ result

station  avg_price
salad    15
grill    14.5

You can stack more than one CTE in the same WITH, separated by commas, and a later one can even build on an earlier one. Each still only runs once, no matter how many times the final query refers to it.

Query

WITH station_totals AS (
  SELECT s.section, d.price
  FROM dishes d
  JOIN stations s ON d.station = s.name
)
SELECT section, SUM(price) AS total_price
FROM station_totals
GROUP BY section
ORDER BY total_price DESC;

↓ result

section  total_price
hot      29
cold     46

A CTE and a subquery can often do the same job. The difference is readability: a CTE gives a mid-step a name you can see, instead of burying it inside another query's parentheses.

On the rail · tonight's orders

ORDER 037

for Eleni


Eleni wants to know which stations are pulling above their weight: sections whose average dish price beats the menu's overall average.

Your query returns

Each station whose average dish price is above the overall menu average, that average included.


ORDER 038

for Konstantinos


Konstantinos is restocking for the hot line specifically, and needs both the matching wines and who to check with before he orders.

Your query returns

Each such wine's name, its paired station, and that station's lead.


ORDER 039

for Eleni


Eleni wants to compare the hot line and the cold line: total menu value at each, added up by section.

Your query returns

Each section (hot or cold) and the combined price of every dish served there.