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)
| Function | Notes |
|---|---|
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 operators | WHERE ms > 100, never ms>100. The parser splits on whitespace. |
| Keywords in the middle are uppercase | AND 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.