Streamhub's product analytics team tracks which pages users are visiting across the platform.
Write a query to return the event ID, user ID, and page path for every event whose event_type is 'page_view'. The page path is stored under the 'page' key in the event's properties JSONB column.
Assumptions:
- The
eventstable has one row per event with anid, auser_id, anevent_type, and apropertiesJSONB column. - A page-view event has
event_type = 'page_view'and a'page'key in itspropertiescarrying the page path as a text value. - Only
'page_view'events should appear. The page-path column carries the text-typed extraction of the'page'key.
Output:
- One row per qualifying event, with columns
id,user_id, andpage_viewed.
Schema · analytics 5 tables
Run previews · Check grades
Write a query, then run it to see results here.
Worked solution Try it yourself first
SELECT
id,
user_id,
properties ->> 'page' AS page_viewed
FROM
events
WHERE
event_type = 'page_view' The shape
JSONB extraction is column-agnostic. The ->> operator works the same way against the analytics events.properties column as it does against products.attributes — the column's name and table don't change how the operator behaves, only the JSONB document it navigates. The page-view filter on event_type is a regular column comparison; the page path is the JSONB extraction.
Clause by clause
SELECT id, user_id, properties ->> 'page' AS page_viewedreturns the event's ID and user ID from their columns, then reaches into thepropertiesJSONB document for the value at the'page'key and returns it as text. TheAS page_viewedalias makes the column read as a domain quantity in the result.FROM eventsreads the event log, where every row has its ownpropertiesJSONB document carrying whatever payload fields the event type recorded.WHERE event_type = 'page_view'filters to page-view events only. This is a plain column comparison —event_typeis a regular text column, not a JSONB field. Filtering on it first means the JSONB extraction in the SELECT only runs against the rows that actually have a'page'key on record.
Why this and not filter on the JSONB field
The same result could be reached by filtering on properties ->> 'event_type' = 'page_view' if the event type lived inside the JSONB document. But here event_type is a top-level column, so filtering on it directly is faster (no per-row JSONB navigation) and clearer. The JSONB extraction in the SELECT happens after the filter, so it only runs against the rows that pass the event_type check. Reaching into JSONB makes sense for fields that vary by event type; reaching past the top-level column to get to a JSONB version of the same field would be the wrong shape.
You practiced JSONB extraction across schemas — the same ->> operator over a different column name (properties instead of attributes); the semantics of the operator are independent of the column it operates on.