N044-H1 Tier 4 · Advanced · hard ecommerce · Brightlane

Return every order's ID, ordered-at timestamp, total amount, the combined `total_amount` across that order plus up to the two immediately preceding orders chronologically, and the count of orders included in that sum

Part of Window Frames (ROWS, RANGE, GROUPS) in SQL

The problem

Brightlane's operations team is building a rolling 3-order revenue report over the global order queue, with both the trailing sum and the count of orders contributing to that sum so the team can spot positions where the window is partial.

Write a query to return every order's ID, ordered-at timestamp, total amount, the combined total_amount across that order plus up to the two immediately preceding orders chronologically, and the count of orders included in that sum.

Assumptions:

  • The rolling-3 window at each row covers that order plus the two orders with the largest ordered_at strictly before it across the entire stream.
  • For the very first order in the stream, the window holds one record, so the count is 1. For the second order, the window holds two records, so the count is 2. From the third order onward, the count is 3.
  • The final result is sorted by ordered_at ascending.

Output:

  • One row per order, with columns id, ordered_at, total_amount, rolling_3_sum, and window_size. Sorted by ordered_at.
Schema · ecommerce 5 tables
categories
id integer
name text
parent_id? integer
products
id integer
name text
category_id integer
price numeric
stock_qty integer
attributes? jsonb
order_items
id integer
order_id integer
product_id integer
quantity integer
unit_price numeric
customers
id integer
name text
email text
city? text
country text
created_at timestamptz
is_active boolean
orders
id integer
customer_id integer
ordered_at timestamptz
status text
total_amount numeric

Run previews · Check grades

Write a query, then run it to see results here.

Worked solution Try it yourself first
Solution query
SELECT
  id,
  ordered_at,
  total_amount,
  SUM(total_amount) OVER (
    ORDER BY
      ordered_at ROWS BETWEEN 2 PRECEDING
      AND CURRENT ROW
  ) AS rolling_3_sum,
  COUNT(*) OVER (
    ORDER BY
      ordered_at ROWS BETWEEN 2 PRECEDING
      AND CURRENT ROW
  ) AS window_size
FROM
  orders
ORDER BY
  ordered_at

The shape

Two window functions can share the same frame definition. SUM and COUNT(*) both use ROWS BETWEEN 2 PRECEDING AND CURRENT ROW, which gives the trailing total alongside the number of rows that actually contributed to it. The count exposes the partial-window positions at the start of the stream as a real column instead of leaving them as silent edge cases.

Clause by clause

  • SELECT id, ordered_at, total_amount, SUM(total_amount) OVER (ORDER BY ordered_at ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS rolling_3_sum, COUNT(*) OVER (ORDER BY ordered_at ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS window_size returns each order plus the two windowed values. Both OVER clauses are identical: no PARTITION BY so the window spans every order; ORDER BY ordered_at sequences the stream chronologically; the same ROWS frame applies to both aggregates.
  • FROM orders reads every order.
  • ORDER BY ordered_at sorts the displayed result chronologically.

Why COUNT(*) and not COUNT(total_amount)

COUNT(*) counts rows in the frame regardless of NULLs in any column. COUNT(total_amount) would count only rows where total_amount is non-null. For a window-size diagnostic, the question is "how many rows is the sum averaging across," not "how many rows have non-null amounts." COUNT(*) answers the diagnostic question directly. If amounts could be NULL and the team needed to flag missing values, COUNT(total_amount) would be the right call instead, and the divergence between the two would itself be the signal.

The trap

The two windows look like they could collapse into one window definition reused twice, but PostgreSQL has no shared-frame syntax in this position. Each window function carries its own OVER clause and the engine optimises identical clauses behind the scenes. Trying to factor the frame out with a named WINDOW clause is possible, but the inline form is the standard idiom for two-aggregate diagnostics. The cost is duplicated text; the benefit is that the relationship between each aggregate and its frame is visible in one place.

You practiced two windowed aggregates over the same trailing frame — SUM and COUNT(*) paired against the same ROWS BETWEEN 2 PRECEDING AND CURRENT ROW, useful for diagnosing partial-window positions at the start of a stream.

How you actually get good at SQL

Reading explains SQL. Writing it, over and over with instant feedback, is what makes you fluent.

That's the whole SQLMaxx loop: 600+ real problems, instant AI feedback, mastery you can actually see, and spaced review that won't let you forget.

A stack of SQL practice problem cards, the top card showing an employees table.
615 problems · 66 concepts

Real problems. Not toy examples.

615 hand-built problems spanning all 66 concepts, from basic SELECTs to window functions, built on real schemas and real business questions, the kind you'll actually get asked on the job. Enough reps to make SQL automatic.

A retro computer showing a SQL query marked correct with a green checkmark.
Instant AI feedback

Write a query. Know if it's right in one second.

No copying an answer and hoping it clicked. The AI grader checks your real query against real data, catches exactly what's wrong, and explains the fix in plain English, like a senior analyst reading over your shoulder on every problem.

A circular mastery progress dial filling from blue to green, the SQLMaxx diamond at its center.
Mastery tracking

Stop guessing whether you actually know it.

SQLMaxx tracks every concept and shows you what you've mastered and what's still shaky. Your skills fill in one concept at a time, so 'I think I get joins' becomes something you can prove.

A SQL query editor circled by a blue return arrow with a clock, scheduled to come back for review.
Spaced review

Learn it once. Keep it for good.

Most of what you learn this week fades by next week. So when a concept comes due for review, SQLMaxx hands you a fresh problem to solve from a blank editor, not a flashcard to re-read. A research-backed spaced-repetition algorithm (FSRS) times each return for right before you'd forget, so your SQL is still there months later, when the interview or the job actually needs it.

Practice, feedback, mastery, review. That's the loop that turns reading into real skill.

Start free

No account, no credit card. Start solving in under a minute.