Write Your First Telemetry SQL Query
Start with a question whose answer you can verify from known synthetic rows. This walkthrough queries the api_request_completed table created in the previous getting-started steps.
Inspect recent rows
Begin with the event grain instead of an aggregate:
SELECT
timestamp_utc,
request_id,
route_template,
status_code,
latency_ms,
release,
environment
FROM api_request_completed
WHERE environment = 'development'
ORDER BY timestamp_utc DESC
LIMIT 100;
Find the synthetic req_demo_001 row. If it is missing or typed incorrectly, return to Verify Event Ingestion and Schema.
Calculate request volume and errors
Once the raw rows look correct, aggregate at the route grain:
SELECT
route_template,
COUNT(*) AS requests,
SUM(CASE WHEN status_code >= 500 THEN 1 ELSE 0 END) AS server_errors,
ROUND(
100.0 * SUM(CASE WHEN status_code >= 500 THEN 1 ELSE 0 END)
/ NULLIF(COUNT(*), 0),
2
) AS server_error_pct
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
AND environment = 'development'
GROUP BY route_template
ORDER BY requests DESC;
The denominator is request volume for each route during the same time window. NULLIF protects the division if the query is later adapted to a join or generated time spine with an empty bucket.
Add latency only after checking the unit
SELECT
route_template,
COUNT(*) AS requests,
approx_percentile_cont(0.5) WITHIN GROUP (ORDER BY latency_ms)
AS p50_latency_ms,
approx_percentile_cont(0.95) WITHIN GROUP (ORDER BY latency_ms)
AS p95_latency_ms
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
AND environment = 'development'
GROUP BY route_template
ORDER BY p95_latency_ms DESC;
Confirm that latency_ms is numeric and always measured in milliseconds before interpreting a percentile. Read SQL Percentiles for sparse groups, approximate functions, and sample-size cautions.
Validate before saving
Use a small fixture with known successful and failed requests. Manually calculate the expected request count and error rate, then compare it with the SQL result.
Check four things:
- Grain: one row represents one completed request.
- Denominator: retries and internal traffic are included or excluded deliberately.
- Window: the newest incomplete bucket is not compared with full buckets.
- Dimensions: route templates, releases, and environments use stable values.
Valid SQL can still answer the wrong business question. Save the definition and exclusions with the query.
Continue
Use the API error-rate recipe for a full schema, fixture, visualization, and alert recommendation. To practice on a connected synthetic database, open the SaaS SQL Lab. Then continue with Create Your First Dashboard and Alert.