CHOMPER WIKI

Pie / donut (SQL)

A Pie panel breaks one dimension into slices — what share of your events falls into each category. Unlike Time series, there's no time bucketing involved: just a category and its size.

Query convention

SELECT event_class AS name, count() AS valueFROM chomper.eventsWHERE timestamp >= parseDateTimeBestEffort({from:String}) AND timestamp <= parseDateTimeBestEffort({to:String})GROUP BY name ORDER BY value DESC

Two columns, aliased name (the slice's label) and value (its size) — one row per slice.

Slice labels

Slices above a configurable size threshold (5% of the total by default) get a name and a leader line outside the donut; smaller slices stay unlabeled so the chart doesn't get crowded with tiny text. Hovering a slice enlarges it slightly and dims the rest, and the legend below always shows each slice's value and share of the total.

Example: Sales by customer type

SELECT JSONExtractString(metadata, 'customer_type') AS name, count() AS valueFROM chomper.eventsWHERE event_class = 'sale' AND JSONHas(metadata, 'customer_type')  AND timestamp >= parseDateTimeBestEffort({from:String}) AND timestamp <= parseDateTimeBestEffort({to:String})GROUP BY nameORDER BY value DESC

customer_type here isn't a raw event field — it's written into metadata at ingestion time by an enrichment function that looks the sale's phone number up in a CRM reference table. It's a good illustration of how enrichment output slots straight into a normal aggregation query, with no special handling needed on the query side.

“Sales by customer type” — B2B vs. Individual, enriched from a CRM lookup.

“Sales by customer type” — B2B vs. Individual, enriched from a CRM lookup.

Advanced example: unnesting a JSON array

A sale's metadata.items is a JSON array — one sale can contain several products. To turn that into “which products sell the most,” unnest the array first, then aggregate:

SELECT JSONExtractString(item_raw, 'name') AS name, sum(JSONExtractInt(item_raw, 'qty')) AS valueFROM (  SELECT arrayJoin(JSONExtractArrayRaw(metadata, 'items')) AS item_raw  FROM chomper.events  WHERE event_class = 'sale'    AND timestamp >= parseDateTimeBestEffort({from:String}) AND timestamp <= parseDateTimeBestEffort({to:String}))GROUP BY nameORDER BY value DESC

JSONExtractArrayRaw splits the array into raw JSON fragments (one per item), and arrayJoin unnests that array into separate rows. Compute the unnest once in a subquery, then extract fields from it in the outer query — calling arrayJoin more than once in the same SELECT doesn't reliably keep multiple unnests aligned to the same item, so avoid that.

Drilling down into a slice

Clicking a slice runs the drill-down query with that slice's category bound as {bucket:String} — the same binding a time series point uses, just holding a category name instead of a date.

Last updated 9 July 2026