SQL operators
Use these operators inWHERE, HAVING, SELECT, and other clauses.
Comparison operators
Null operators
Text-matching operators
For wildcard behavior and the 65KB limit, see Pattern matching. For
MATCH and search(), see Full-text search.
Logical operators
Arithmetic operators
INCLUDES, NOT INCLUDES, and CONTAINS are BTQL-only operators and raise a syntax error in SQL mode. For exact array membership in SQL mode, use IN and NOT IN (e.g., tags IN ('value')). MATCH is a fuzzy approximation that tokenizes text, so tags MATCH 'value' also matches values containing the term as a token, such as value-added.SQL functions
Use these functions inSELECT, WHERE, and GROUP BY clauses, and in aggregate measures.
Date and time functions
date_trunc accepts 'second', 'minute', 'hour', 'day', 'week', 'month', or 'year', or a positive integer multiple of second(s), minute(s), hour(s), or day(s) (for example, '15 minutes' or '2 hours'). The 'week', 'month', and 'year' intervals don’t accept multiples because they have variable durations.String functions
Array functions
JSON functions
Use
json_extract when a field’s value is a JSON-encoded string rather than a native object. For native object and array access, use field access instead. See Extract data from JSON strings for worked examples.
Null-handling functions
coalesce(field, 'x') != 'y' is automatically rewritten to field <!=> 'y' for better index performance.Type conversion and cast functions
Search functions
search(query) is equivalent to writing input MATCH query OR output MATCH query OR ... for each text field. When log search optimization is enabled on the project, search() uses bloom filters to skip irrelevant segments automatically. Shingled search optimization extends this to multi-word and phrase queries. See Full-text search.
Cost functions
On the
spans and traces shapes, estimated_cost() and metrics.estimated_cost are populated on LLM spans, not the root/task span. Filtering to is_root = true returns null cost. To get a trace’s total cost, sum across its spans with sum(estimated_cost()). The summary shape rolls this up per trace automatically.Valid component names for estimated_cost_breakdown() and estimated_cost_component(): promptUncachedTokensCost, promptCachedTokensCost, promptCacheCreationTokensCost (single-tier cache creation), promptCacheCreation5mTokensCost and promptCacheCreation1hTokensCost (two-tier cache creation, e.g. Anthropic), completionTokensCost, and totalCost.Aggregate functions
Aggregate functions are available only in measures or withGROUP BY.
Conditional expressions
SQL supports conditional logic throughCASE WHEN for multi-branch conditions, IF for two-branch conditions, and COUNT_IF for conditional aggregation.
CASE WHEN
Use CASE WHEN ... THEN ... ELSE ... END for one or more branches:
IF and COUNT_IF
For two-branch conditions, IF(condition, then_value, else_value) is a shorter alternative to CASE WHEN. Use CASE WHEN when you need more than two branches.
COUNT_IF(condition) counts rows where the condition is true. It is equivalent to count(CASE WHEN condition THEN 1 ELSE NULL END).
IF composes with other aggregates. For example, count distinct users who hit a condition:
Next steps
- Learn how to structure queries in the SQL reference.
- Browse copy-and-run patterns in Example queries.
- Optimize slow or incorrect queries with SQL best practices.