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

Return every category ID and a JSON array of `'color'` attribute values for products in that category, pulling each color from the product's `attributes`

Part of JSONB Aggregation (jsonb_agg, json_build_object) in SQL

The problem

Brightlane's product color index records the color attribute for every product in each category.

Write a query to return every category ID and a JSON array of 'color' attribute values for products in that category, pulling each color from the product's attributes.

Assumptions:

  • Each category_id with at least one product should appear once.
  • For each category, the array contains one element per product in that category. Products with a 'color' key in attributes contribute their text color value; products without a 'color' key contribute a JSON null array element.
  • The order of elements within each array is unspecified.

Output:

  • One row per category, with columns category_id and colors.
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
  category_id,
  JSONB_AGG(attributes ->> 'color') AS colors
FROM
  products
GROUP BY
  category_id

The shape

attributes->>'color' extracts the color value as text for each product, returning NULL when the 'color' key is absent. jsonb_agg then collects every one of those values — NULLs included — into a JSON array, converting each NULL to a JSON null element. Every product in the category gets one element in the array, color or no color.

Clause by clause

  • SELECT category_id, jsonb_agg(attributes->>'color') AS colors returns the grouping column and the per-group array. The ->> operator returns text, so present colors come out as text strings and absent colors come out as NULL text values. jsonb_agg then represents each text value as a JSON string in the array, and each NULL as a JSON null.
  • FROM products reads the product records.
  • GROUP BY category_id partitions by category. For category 4 (books) every product is missing a 'color' key, so the array comes out as six JSON nulls in a row. For category 8 (men's clothing) three of the five products have a color and two don't, so the array is [null, "Navy", null, "Olive", "Blue"].

The trap

The behaviour of jsonb_agg on NULL inputs is the load-bearing thing here, and it cuts against the usual aggregate intuition. COUNT(col) skips NULLs. SUM(col) skips NULLs. jsonb_agg(col) does not skip NULLs — it preserves them as JSON null elements in the array. That is exactly why the audit shape works: every product contributes an element, even the ones without a color on record, and the array length per category matches the product count per category. If you swap in jsonb_agg(attributes->>'color') FILTER (WHERE attributes->>'color' IS NOT NULL) thinking the nulls need explicit handling, the array shrinks to only the products with a recorded color, and categories like 4 disappear from the output entirely because every row in the group has been filtered away from the aggregate.

You practiced jsonb_agg(attributes ->> 'key') — the aggregate includes JSON null for records where the extracted value is missing, preserving one element per source record.

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.