Skip to content
    SeaCode
    Learning tracksCode ArenaWorkshops & EventsInstructors
    Log inSign up
    SQLSQL

    First questions to the data

    • What are SQL and databases?
    • SELECT: choosing columns
    • WHERE: filtering rows
    • ORDER BY and LIMIT: sort and take the top

    Summarizing and grouping

    • Aggregates: COUNT, SUM, AVG
    • GROUP BY and HAVING
    • CASE, COALESCE and text functions

    Joining tables

    • Keys and relationships
    • INNER JOIN
    • LEFT JOIN: leave nobody out
    • Three-table joins and self joins
    • Subqueries and CTEs

    Building tables and changing data

    • CREATE TABLE and constraints
    • INSERT, UPDATE and DELETE
    • Transactions: all or nothing
    • SQL injection: the most dangerous mistake

    Professional level

    • Indexes: why is my query slow?
    • Window functions: rankings and totals without losing rows
    • Designing tables: normalization
    • Project: analytics for a learning platform
    SQL

    Joining tables · Lesson 12 of 20

    Subqueries and CTEs

    A query inside a query, and WITH to break a problem into steps.

    11 minutes2 games

    Sometimes you need a number before you can ask: "who's above average?" The average itself is a query. A subquery is a query in brackets inside another, and it runs first.

    SQL
    SELECT name, xp
    FROM students
    WHERE xp > (SELECT AVG(xp) FROM students)
    ORDER BY xp DESC;

    A subquery can return a list too, used with IN. Or use EXISTS, which asks "is there at least one row?":

    SQL
    -- Students taking at least one web course
    SELECT name
    FROM students s
    WHERE EXISTS (
      SELECT 1
      FROM enrollments e
      JOIN courses c ON c.id = e.course_id
      WHERE e.student_id = s.id AND c.track = 'web'
    );

    That subquery uses s.id from the outer query, so it runs per student. That's a correlated subquery.

    WITH (CTE): one step at a time

    Nested subqueries get hard to read. WITH lets you name an intermediate result (like a variable) and use it afterwards. That's a Common Table Expression.

    SQL
    WITH per_student AS (
      SELECT student_id,
             COUNT(*) AS courses,
             AVG(progress) AS avg_progress
      FROM enrollments
      GROUP BY student_id
    )
    SELECT s.name, p.courses, ROUND(p.avg_progress) AS avg_progress
    FROM per_student p
    JOIN students s ON s.id = p.student_id
    WHERE p.courses >= 2
    ORDER BY p.avg_progress DESC;

    WITH per_student: one row per student with course count and average progress

    JOIN students for the names

    WHERE and ORDER BY on the ready result

    Important

    A CTE is usually neither faster nor slower, just clearer. A special form, WITH RECURSIVE, walks trees and hierarchies (the manager's manager…), which has no easy alternative.

    What's the output?

    SELECT COUNT(*) AS above_avg
    FROM students
    WHERE xp > (SELECT AVG(xp) FROM students);

    What will this code print?

    Interview question

    When do you use a subquery, a JOIN, or a CTE?

    Exercise

    Using WITH: compute each student's average progress, then get the name of students whose average is above 60, alphabetically.

    Expected result:
    name
    Karim
    Laila
    Nour
    SQL
    WITH avg_progress AS (
      SELECT student_id, AVG(progress) AS avg
      FROM enrollments
      GROUP BY student_id
    )
    SELECT
    

    Learn more from

    • PostgreSQL docs: WITH queries (CTEs)postgresql.org
    • PostgreSQL docs: Subquery expressionspostgresql.org
    • Modern SQL: WITHmodern-sql.com
    • SQLite: WITH clausesqlite.org

    Played 0 of 2 games

    Sign in to save your progress and earn XP.

    PreviousThree-table joins and self joinsNextCREATE TABLE and constraints
    SeaCode

    Learn to code for real, online or at our branch in front of Cairo University, Giza.

    Learn

    • All courses
    • Interactive tutorials
    • Interview practice problems
    • Mock interview
    • Learning tracks
    • Code Arena
    • Workshops & Events
    • Knowledge library
    • Team projects

    Your account

    • Log in
    • Sign up
    • Learning plan
    • Certificates
    • Site map

    Contact us

    • WhatsApp
    • 010 9094 1104
    • In front of Cairo University, Giza

    © 2026 SeaCode. All rights reserved.