runtime
38 / 88

lesson 38 Window functions · intermediate

Logical query processing & row grain

Follow query processing and track what one row represents.

the idea

Think FROM/JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. This is a logical model, not a promise about physical execution. Row expressions preserve rows, aggregates collapse them, and windows add context without collapsing.

tables in this lesson

The challenges use this data. Each column shows its type underneath; → marks a link to another table.

orders6 columns · 12 rows
idinteger · keycustomer_idintegerproduct_idintegerquantityintegerstatustextordered_attext
101112paid2025-01-01
102231paid2025-01-02
103121paid2025-01-05
104352pending2025-01-08
105445paid2025-02-01

showing 5 of 12 rows

example

The idea in one query. Press Run to see what it returns; running examples never affects your progress.

example.sql
SELECT customer_id,SUM(quantity) AS units
FROM orders
WHERE status='paid'
GROUP BY customer_id
HAVING SUM(quantity)>2
ORDER BY units DESC;

Watch for: SQLite accepts some alias usages other engines reject. Prefer clear expressions or an outer query for portable SQL.

build it step by step

Each step changes one thing. Run them in order and watch the result change.

  1. Start with rows. One row is one paid order line.

    step-1.sql
    SELECT id,customer_id,quantity
    FROM orders
    WHERE status='paid';
  2. Aggregate. Customers become the output grain.

    step-2.sql
    SELECT customer_id,SUM(quantity) AS units
    FROM orders
    WHERE status='paid'
    GROUP BY customer_id;
  3. Filter groups. HAVING works on the totals, then ordering shapes the output.

    step-3.sql
    SELECT customer_id,SUM(quantity) AS units
    FROM orders
    WHERE status='paid'
    GROUP BY customer_id
    HAVING SUM(quantity)>2
    ORDER BY units DESC,customer_id
  4. Keep individual rows instead. A window attaches the customer total while retaining order rows.

    step-4.sql
    SELECT
      id,
      customer_id,
      quantity,
      SUM(quantity) OVER(PARTITION BY customer_id) AS customer_units
    FROM orders
    WHERE status='paid'

challenge 1

Return customer_id and units for paid orders grouped by customer; keep groups with units >2. Sort units descending, then customer_id ascending.

Return customer_idunitsrows in the order asked

challenge-1.sql
 
To master this lesson, solve both challenges without hints and pass the concept check. 3 of 3 to go.