SimpleTelemetry

SQL

The entire query language, on one page.

Shape

SELECT expr [AS name] , ...
FROM one_table
WHERE condition
GROUP BY expr , ...          -- up to 3 keys
ORDER BY output [ASC|DESC]   -- one, must name a SELECT output
LIMIT n

One table per query, no joins, no subqueries. -- and /* */ comments are fine.

Functions (all of them)

FunctionNotes
COUNT(*)row count. There's no COUNT(col) or COUNT(DISTINCT …).
SUM(x)
AVG(x)always shown with 2 decimals.
MIN(x) MAX(x)
PERCENTILE(x, p)0 < p < 100, fractions fine: PERCENTILE(ms, 99.9). Fast estimate (within a few percent), not exact.
RATE(x)dashboard cards only: turns an aggregate into a per-second rate. See Charts.

There are no scalar functions: no NOW(), DATE_TRUNC, ROUND, LOWER, COALESCE. You won't need them: time math is integer arithmetic and charts handle the time axis for you.

Conditions

WHERE ms >= 100 AND ( region = 'eu' OR region = 'us' )
WHERE status IN ( 'ok' , 'cached' )
WHERE ms BETWEEN 100 AND 500
WHERE region IS NOT NULL

Comparisons: = != <> > >= < <=, combined with AND / OR and parentheses. Arithmetic: + - * /. The divisor must be a positive whole-number constant (time / 3600 works, a / b doesn't). CASE WHEN cond THEN value ELSE value END works in expressions, and ELSE is required. Strings compare with = and != only.

Three rules that will save you a minute

Spaces around operatorsWHERE ms > 100, never ms>100. The parser splits on whitespace.
Keywords in the middle are uppercaseAND OR IN BETWEEN IS NULL CASE WHEN THEN ELSE END must be written in caps. SELECT, FROM, functions and true/false are any case.
Strings use single quotes'eu', not "eu". Column names are never quoted.

Grouping and ordering

SELECT region , AVG(ms) AS avg_ms
FROM http_request
GROUP BY region
ORDER BY avg_ms DESC
LIMIT 10

Up to 3 group keys, and keys can be expressions (GROUP BY time / 3600 is an hourly bucket). Mixing aggregates with plain columns requires the plain columns in GROUP BY. One ORDER BY, and it must name a SELECT output: give the output an AS alias and order by that. Results cap at 32,768 rows.

Time and null

Every table has time: epoch seconds, stamped at ingest. It's a normal integer, as in WHERE time >= 1786250180, but inside dashboard cards you shouldn't write time filters at all; the card injects the window and buckets for you. Nulls never match any comparison (use IS NULL / IS NOT NULL), are skipped by aggregates, and rows with a null group key are dropped.