Querying History
From a screen
| Component | Use |
|---|---|
| HmiTrendChart | Live trend of one or more tags, with a rolling window |
| Historian | Historical chart with time-range controls and statistics |
| Sparkline / HmiSparkline | A value's recent shape, inline |
Bind the tag list and the chart does the rest — window selection, downsampling and aggregation are handled server-side.
From a script
data = system.hist.getTrends(
["Line1/Filler/Motor1/Speed", "Line1/Filler/Motor1/Current"],
"2026-08-01T00:00:00Z",
"2026-08-02T00:00:00Z",
maxPoints=500,
agg="avg",
)
const data = await system.hist.getTrends(
["Line1/Filler/Motor1/Speed"],
start, end, 500, "minmax",
);
| Parameter | Meaning |
|---|---|
paths | Tag paths |
start, end | ISO-8601 timestamps |
maxPoints | Downsample target — the server aggregates to about this many points |
agg | avg or minmax |
Aggregation
| Mode | Keeps | Use for |
|---|---|---|
avg | The mean per bucket | Smooth analogue trends — temperature, pressure, level |
minmax | The extremes per bucket | Anything where spikes matter — current, vibration, pressure transients |
avg hides spikes. A 200 ms current spike averaged into a one-minute bucket disappears
completely. If the excursion is the reason you are looking, use minmax.
Always set maxPoints
A day of one-second data is 86,400 points per tag. A chart 1,200 pixels wide can draw about 1,200. Transferring the rest costs bandwidth, browser memory and render time, and shows nothing.
| Window | A sensible maxPoints |
|---|---|
| Last hour | 300–600 |
| Last day | 500–1,000 |
| Last week | 1,000–2,000 |
| Last month | 1,000–2,000 |
The server aggregates down to your target using the rollup where appropriate, so a long window does not mean a slow query.
Statistics
Range-mode statistics give the per-tag summary shown beside a chart when a date range is selected:
| Statistic | Notes |
|---|---|
| min / max | Extremal |
| first / last | From the outermost part of the window that has data |
| count / sum | Additive |
| avg | Reconstructed exactly, not averaged |
| variance, standard deviation | Reconstructed exactly from (Σx², Σx, n) |
That last point matters across epochs. An average of averages is wrong whenever the parts hold different sample counts, and a mean of variances is meaningless — so QUBIQ recombines from the underlying sums instead. The same decomposition is what the rollup materialises.
Live versus range mode
| Mode | Behaviour |
|---|---|
| Live | A rolling window that follows now; new samples push in. Shows the instantaneous current value. |
| Range | A fixed window. Shows aggregate statistics for the window. |
In live mode, the live tail buffer merges the most recent in-memory samples into the result, so the chart's leading edge is genuinely live despite QuestDB's batched flush.
Performance
| Symptom | Cause | Fix |
|---|---|---|
| Slow long-range query | Reading the base table instead of the rollup | Rebuild the rollup if stale |
| Slow query on any range | Too many tags at once | Split across charts, or reduce the series |
| Browser sluggish after loading a chart | maxPoints too high | Lower it |
| Trend has gaps | Deadband too large, or the source was down | Compare against connection health for the period |
| Trend flat-lines then jumps | Store interval absent on a slow-moving tag | Set a store interval |
| Trend stops at a date in the past | An epoch boundary with a retired store | Check the historian's epochs |
Interpreting a trend honestly
- A deadband means the stored trend is not the raw signal. That is intended, but know the deadband before drawing conclusions about noise.
avgaggregation smooths. Switch tominmaxbefore concluding an excursion did not happen.- A gap can be missing data or a genuinely static value. A store interval removes the ambiguity.
- Bad-quality periods are not the same as zero. Check quality alongside value when a trend drops to nothing.
Exporting history
For reports and analysis outside QUBIQ:
- A Gateway script that queries
system.hist.getTrends, formats the result and writes it withsystem.files.save— then hands the URL to a screen or a notification. - A pipeline on a schedule doing the same and pushing to an external system.
- Direct SQL against QuestDB via a named query, for tools that speak Postgres wire.
Next
→ Security