Python Central HubSign in

Data Analytics with Python / Phase 9: SQL for Data Analytics

CTEs (WITH) and Subqueries

Write clean analytics SQL using CTEs, plus when to use subqueries.

Why CTEs

CTEs (Common Table Expressions) improve readability.

  • Break complex queries into steps
  • Reuse derived results

Example: revenue by country for paying users

SQL
WITH paying_users AS (
  SELECT user_id, country
  FROM users
  WHERE plan != 'free'
),
revenue_by_user AS (
  SELECT user_id, SUM(amount) AS revenue
  FROM orders
  GROUP BY user_id
)
SELECT
  u.country,
  SUM(r.revenue) AS revenue
FROM paying_users u
JOIN revenue_by_user r ON r.user_id = u.user_id
GROUP BY u.country
ORDER BY revenue DESC;

Subqueries

Subqueries are inline “nested” queries.

SQL
SELECT *
FROM (
  SELECT user_id, SUM(amount) AS revenue
  FROM orders
  GROUP BY user_id
) t
WHERE t.revenue >= 1000;

Practical guidance

  • Prefer CTEs for multi-step analytics.
  • Keep each CTE small and well-named.

A CTE is a named pipeline stage

Think of each WITH name AS (...) block as a labeled step in a pipeline. Later steps (and the final SELECT) can reference any earlier CTE by name, the same way a variable in a script holds a value you compute once and reuse.

diagram CTE pipeline mermaid
Each WITH block is a named, reusable step; later steps and the final SELECT can reference any earlier CTE by name.

Check your understanding

quizCheck yourself
  1. What is the main benefit of a CTE?

    Show answer

    A — Readability: break a complex query into named steps — CTEs improve readability and let you reuse derived results within one query.

  2. In the CTE example, what does the paying_users CTE contain?

    Show answer

    A — Users whose plan is not free — It selects user_id and country from users WHERE plan != 'free'.

  3. How long does a CTE exist?

    Show answer

    B — Only for the one query it is attached to — A CTE is not a saved table. If you copy it into many queries, consider a view.

  4. What does the subquery example return?

    Show answer

    A — Users with at least 1000 in total revenue — The inner query sums amount per user and the outer WHERE keeps t.revenue >= 1000.

🧪 Try It Yourself

Exercise 1 – A single CTE

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 2 – Two CTEs joined together

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 3 – Filter with a subquery in WHERE

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Next

Date and Time Analytics in SQL applies these same aggregation and window patterns to the most common analytics dimension of all: time.

Was this page helpful?

Let us know how we did