Charts
Chart types, when each one is right, and how to configure axes, series, and formatting.
A chart binds a dataset to a visual form. It stays bound: when the dataset syncs, the chart updates.
Create a chart
Pick a dataset, then a chart type, then assign fields to the chart’s roles — usually an x (dimension), a y (measure), and optionally a series (split).
Dataset: Orders
x: created_at → truncated to month
y: total → sum
series: status
type: stacked bar
Choosing a type
| Type | Use for | Avoid when |
|---|---|---|
| Line | A measure over time | Categories with no order |
| Area | Cumulative totals over time | Comparing many series |
| Bar | Comparing categories | More than ~25 categories |
| Stacked bar | Composition within a total | Comparing individual segments precisely |
| Grouped bar | Comparing series side by side | Many series — it gets noisy |
| Scatter | Relationship between two measures | Categorical axes |
| Table | Exact values, many columns | Spotting shape or trend |
| Metric | One headline number | Anything needing context |
| Map | Values by geography | Data without a geographic field |
When in doubt, bar for categories, line for time
Most chart-choice mistakes are a pie chart that should have been a bar chart, or a bar chart of dates that should have been a line.
Aggregation
Every measure needs an aggregation, because a chart shows fewer rows than the dataset has.
| Aggregation | Notes |
|---|---|
sum |
Default for amounts |
avg |
Watch for nulls — they are excluded, not zero |
count / count distinct |
count distinct is heavier on large datasets |
min / max |
Useful for ranges |
median / p95 |
Better than avg for latency and price |
avg of an avg is not an avg
Averaging a column that is already an average weights every group equally regardless of size. Aggregate from the raw measure instead.
Time handling
| Setting | Options |
|---|---|
| Truncate | hour, day, week, month, quarter, year |
| Timezone | Team default, or per chart |
| Range | Fixed dates, or relative (last 90 days) |
| Compare | Previous period, or same period last year |
Partial periods look like a crash
The current month is incomplete, so it always dips. Enable Exclude current period on trend charts, or label it clearly.
Formatting
- Number format — decimals, thousands separator,
€/%prefix or suffix, compact (1.2M). - Colour — a team palette by default; assign fixed colours per series so
paidis the same green everywhere. - Axis — override the label, set an explicit min/max, or use a log scale.
- Null handling — show as gaps, as zero, or interpolate. Gaps are the honest default.
A truncated y-axis exaggerates change
Starting a bar chart’s axis at a non-zero value makes a 2% change look like a collapse. For bars, keep zero in range; for lines, truncation is acceptable when labelled.
Transforms
Applied after the query, before rendering:
| Transform | Effect |
|---|---|
| Top N | Keep the largest N, group the rest as “Other” |
| Cumulative | Running total across the x axis |
| Moving average | Smooth over N periods |
| Percent of total | Convert to share |
| Derived field | An expression over existing fields |
margin_pct = (revenue - cost) / revenue * 100
Cross-dataset charts
Coming soon
A chart reads one dataset today. Combining two requires a shared mapped field, and field mapping is still in development — see Mappings.
Export
| Format | Contents |
|---|---|
| PNG / SVG | The rendered chart |
| CSV | The chart’s result rows, post-transform |
| Query | The generated SQL, to run yourself |
Exports respect permissions — a Viewer can export what they can see.