The formula language
Halo's formula syntax in full: fields, values, operators, types, missing values, aggregates, parameters and every function.
A formula reads like a spreadsheet formula, refers to a dataset's fields and report parameters, and compiles to your source's SQL. It needs no SQL permission, and runs the same on PostgreSQL, Redshift and Dremio, and in DuckDB for extracts and uploaded files. Other sources say "Formulas can't run on … sources yet" until they're supported.
SUM([Revenue]) / SUM([Orders])
IF([Region] = 'North', 'Northern', 'Elsewhere')
IF(WEEKDAY([Order date]) >= 6, 'Weekend', 'Weekday')
SUM([Revenue]) / @targetFields
Refer to a field by its label in brackets or by its name.
[Average order]finds the field labeled Average order. Labels always go in brackets.revenuefinds the field namedrevenue. A name of letters, digits and underscores that doesn't start with a digit needs no brackets; any other name does, as in[2026 target].Case doesn't matter when only one field fits, so
Revenuefindsrevenue.Names come first. If one field is named
regionand another is labeled Region,[Region]is the one namedregion.If two fields share a label, the editor asks you to write the one you mean by name.
Inside brackets,
]]writes a].
Saving stores each reference by name and Halo Data shows it with the current label, so renaming a label never breaks a formula. Completion (Ctrl+Space) matches labels and names.
A field's value is its value in each row: [Revenue] - [Cost] subtracts row by row. A field that's already an aggregate, such as another aggregate formula, is that aggregate.
Values
| Kind | Written as |
|---|---|
| Numbers | 42, 3.14, .5, 1e6, -1 |
| Text | 'North' or "North". A backslash escapes a quote or backslash: 'it\'s'. \n and \t work too |
| True and false | TRUE, FALSE |
| Missing | NULL |
| Dates | DATE '2026-07-04' |
| Dates and times | TIMESTAMP '2026-07-04 21:30', in the report's time zone |
Text next to a date is read as a date, so [Order date] >= '2026-06-01' works. Every value in a formula reaches the source as a bind parameter, never as SQL text.
// starts a comment that runs to the end of the line.
Operators
From loosest to tightest:
| Operators | Means |
|---|---|
OR | Either is true |
AND | Both are true |
NOT | The condition is false |
= != <> < <= > >=, IN (…), NOT IN (…), IS NULL, IS NOT NULL | Compare two values, match a list, or check whether a value is missing |
+ - | Add and subtract numbers |
* / | Multiply and divide |
- | Negate |
Parentheses group. Comparisons take two values at a time. / always gives a number, never whole-number division.
+ works on numbers only. Join text with CONCAT, move dates with DATE_ADD and count between them with DATE_DIFF.
Conditions
IF(condition, then, else), IFNULL, COALESCE and NULLIF are functions. CASE is syntax, in two forms:
CASE WHEN [Orders] >= 1000 THEN 'Busy'
WHEN [Orders] >= 100 THEN 'Steady'
ELSE 'Quiet' END
CASE [Region] WHEN 'North' THEN 'Northern' ELSE 'Elsewhere' ENDAll results share one type.
Types
Formulas use the field types, in words: number, whole number, text, true/false, date, and date and time. Whole numbers widen to numbers and dates to dates and times where they meet, so IF(x, 1, 2.5) is a number. A formula field's type is its formula's: Halo Data shows it as you type, and saving sets it.
Missing values
A missing value is NULL in a formula and shows as a dash in a chart or table.
Aggregates skip it:
SUM,AVG,MIN,MAX,MEDIAN,COUNTandCOUNT_DISTINCTignore missing values.COUNT_ROWS()counts every row.Dividing by zero gives a missing value, not an error, so
SUM([Revenue]) / SUM([Orders])needs no guard.= NULLis never true, so it's an error that suggestsIS NULL.IFtakes its else when the condition is missing.CASEwithout anELSEis missing when nothing matches.IFNULL(value, fallback)andCOALESCE(a, b, …)swap in a value.NULLIF(value, other)makes one missing, such as an empty string.
Aggregates and row formulas
A formula with an aggregate function (
SUM,AVG,MIN,MAX,COUNT,COUNT_DISTINCT,COUNT_ROWS,MEDIAN,PERCENTILE) is a measure. It has no aggregate of its own, charts can't re-aggregate it, and it can't be a dimension.A formula without one is a row formula: a dimension, or a measure that charts aggregate (sum by default for numbers, count distinct otherwise).
Aggregates and row values can't mix, and aggregates can't nest. Literals and parameters fit either.
Parameters
A parameter is a value reports set, written @name, such as SUM([Revenue]) / @target. Declare them on the dataset's Fields tab under Report parameters, each with a label, a name (lowercase letters, digits and underscores), a type and a default. A report's value takes over from the default, and a value that doesn't fit the type is an error.
Parameters work in row formulas and aggregates alike. See Filters and parameters for the report side.
Dates and time zones
Dates and times reach formulas as wall-clock time in the report's time zone, so HOUR([Shipped at]) is the local hour. TODAY() and NOW() are the report's today and now.
DATE_TRUNC follows your organization's calendar: 'week' starts on its week start, 'fiscal_quarter' and 'fiscal_year' on its fiscal year, and 'iso_week' on Monday. WEEK() is always the ISO week and WEEKDAY() runs from 1 for Monday to 7 for Sunday. See Dates, time zones and fiscal calendars.
When a formula has a mistake
Formulas are checked as you type. Each mistake is underlined and says what to do:
"SUM needs a number; Region is text." with "To count text values, use COUNT or COUNT_DISTINCT."
"No field is named revnue. Did you mean revenue?"
"DATE_TRUNC doesn't know the unit months. Did you mean 'month'?"
"These formulas use each other in a loop: Margin → Cost ratio → Margin. Break the loop in one of them."
A formula that refers to a broken one says which field to fix. Saving a definition with a broken formula fails with the same message.
Functions
Every function, with its signatures and examples. Search by name or by what it does.