N047-H2 Tier 4 · Advanced · hard ecommerce · Brightlane

Return the product ID, category ID, name, and price for every product whose `price` equals the highest `price` within its own category

Part of Correlated Subqueries in SQL

The problem

Brightlane's merchandising team wants the highest-priced product in each product category for a premium catalog review. Products awaiting categorization (those with a missing category_id) are excluded from the analysis.

Write a query to return the product ID, category ID, name, and price for every product whose price equals the highest price within its own category.

Assumptions:

  • Products with a missing category_id should not appear in the result.
  • A category's highest price is the largest price across products in that category_id.
  • A product qualifies when its price is exactly equal to its own category's highest price. When multiple products in the same category share the same highest price, every tied product qualifies.

Output:

  • One row per qualifying product, with columns id, category_id, name, and price.
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,
  category_id,
  name,
  price
FROM
  products p
WHERE
  price = (
    SELECT
      MAX(price)
    FROM
      products inner_p
    WHERE
      inner_p.category_id = p.category_id
  )

The shape

The condition is "this product's price equals the highest price within its own category," which is a correlated equality against a per-category \MAX\. The outer \WHERE\ compares each product's \price\ to the maximum across products sharing the same \category_id\, and equality keeps every tied product in the category at that maximum price.

Clause by clause

  • \SELECT id, category_id, name, price\ returns the four columns the spec asks for, taken straight from the qualifying product row.
  • \FROM products p\ reads every product and aliases the table as \p\ so the inner subquery can correlate to the outer product's category.
  • \WHERE price = (SELECT MAX(price) FROM products inner_p WHERE inner_p.category_id = p.category_id)\ is the correlated equality filter. The inner alias \inner_p\ distinguishes the inner products rows from the outer \p\. The predicate \inner_p.category_id = p.category_id\ ties the inner \MAX\ to the same category as the outer row, so every product is compared against the highest price within its own category. Equality rather than \>=\ against the maximum is what allows multiple tied products in the same category to all qualify.

The trap

The exclusion of products with a missing \category_id\ is not implemented by an explicit \WHERE p.category_id IS NOT NULL\ clause. It falls out of NULL semantics in the correlated predicate. For a product with \category_id = NULL\, the inner \WHERE inner_p.category_id = p.category_id\ evaluates to NULL for every inner row, because comparing anything to NULL with \=\ yields NULL, not true. The inner subquery returns no rows, \MAX(price)\ over zero rows returns NULL, and the outer \price = NULL\ also evaluates to NULL rather than true. A predicate that is NULL never passes a \WHERE\, so the row is dropped without ever needing an explicit IS NULL filter. The same NULL-propagation logic is also why an attempt to handle the exclusion with \!=\ would silently miss it. \p.category_id != NULL\ is NULL, not true, and would drop every row in the table. The rule is: \IS NULL\ and \IS NOT NULL\ are the only safe predicates against NULL, and a correlated equality predicate against a NULL outer value implicitly excludes that outer row by the same mechanism.

You practiced a correlated subquery whose inner predicate references the outer row's category — each candidate product is compared against the maximum within its own category, with missing-category products implicitly dropped by the predicate's NULL semantics.

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.