Brightlane's book catalog export pipeline needs a structured JSON document per paperback product that combines standard product columns with a JSONB attribute.
Write a query to return a JSON object for every product whose 'format' attribute is 'Paperback'. The object must have keys 'id', 'name', and 'pages', where 'pages' is the value extracted from the product's attributes under the 'pages' key.
Assumptions:
- The
productstable has one row per product with anid, aname, and anattributesJSONB column. - A paperback product has its
'format'key set to'Paperback'and a'pages'key inattributes. - Only paperback products should appear. Each output row carries one JSON document combining the product's
id,name, and the text-extracted'pages'value.
Output:
- One row per paperback product, with one column,
book_spec, containing the JSON document.
Schema · ecommerce 5 tables
Run previews · Check grades
Write a query, then run it to see results here.
Worked solution Try it yourself first
SELECT
JSON_BUILD_OBJECT('id', id, 'name', name, 'pages', attributes ->> 'pages') AS book_spec
FROM
products
WHERE
attributes ->> 'format' = 'Paperback' The shape
json_build_object accepts any expression as a value, including the ->> extraction from a JSONB column. Mixing the relational columns id and name with the JSONB-extracted attributes->>'pages' inside one call produces a single output document per row, blending data from both sources.
Clause by clause
SELECT json_build_object('id', id, 'name', name, 'pages', attributes->>'pages') AS book_specbuilds the JSON document for each surviving row. The first two values come straight from the column, soidlands as a JSON number andnameas a JSON string. The third value comes fromattributes->>'pages', which extracts the'pages'key from the JSONB column as text — that is why"pages": "431"appears in the result with the value quoted as a JSON string.FROM productsreads the product records.WHERE attributes->>'format' = 'Paperback'restricts the input to products whose'format'attribute is the text'Paperback'. Only four rows survive the filter —Writing Clean Code,The Efficient Developer,Relational Databases in Practice, andImproving Existing Code— and the function runs once per surviving row.
Why this and not ->
attributes->'pages' returns the JSONB value (which would carry the source type — quoted string if stored as a JSONB string, number if stored as a JSONB number). attributes->>'pages' returns text. The prompt does not require the page count as a number, and the reference result shows "pages": "431" as a string, so the text-extracting ->> is the right choice. Forcing a numeric type would be a separate cast and a different problem.
You practiced mixing relational columns and JSONB-extracted values inside json_build_object — the function accepts any expression as a value, including ->>-extracted strings.