Query structure

A FeatureQL query defines features, selects which ones to return, and binds concrete values to their inputs. You can then filter, sort, and paginate the results — just like SQL.

Grain is the entity level of a result row (one customer, one order, one group). WHERE and RETURN must stay at the same grain. Row filters that run before aggregation belong on FILTER (WHERE …) inside each aggregate. See Grouping and unnesting .

Anatomy of a query

[DEFINE
    feature_name := expression, -- Feature definition
    ...
]
RETURN
    feature_name, -- Feature to evaluate and return
    ...
[FROM namespace, ...]
[FOR feature_name := BIND(), ...] -- Bind values to inputs
[WHERE boolean_expression] -- Filter presented rows (RETURN grain)
[ORDER BY expression [ASC|DESC] [NULLS FIRST|LAST], ...] -- Sort results
[LIMIT count [OFFSET count]] -- Paginate results

Each clause has a specific role:

ClauseDescription
DEFINEDefines features locally, on top of what already exists in the registry.
RETURNLists the features to evaluate and return.
FROMDefines one or more namespaces to pull features from.
FORBinds concrete values to the query's inputs. Without binding, a query with features depending on INPUT() features won't execute.
WHEREFilters presented rows after resolution. Features in WHERE need not appear in RETURN, but they must be at the same grain as what you show (group keys, measures, or booleans derived from them). Pre-aggregation row filters belong on FILTER (WHERE …) of each aggregate — not here. Mixed or finer-grain WHERE raises UE/STATIC-ANALYSIS-WHERE-FINER-THAN-RETURN.
ORDER BYSorts the results. Supports ASC/DESC and NULLS FIRST/NULLS LAST.
LIMIT
OFFSET
Controls pagination.

Top-level SQL-shaped GROUP BY and HAVING clauses are rejected. FeatureQL grouping is expressed inside feature computations; see Grouping and unnesting .

Intermediate features with DEFINE

Complex queries often need intermediate calculations that shouldn't appear in the output. The DEFINE clause defines features that are available for computation but excluded from the result:

FeatureQL
DEFINE
    number1 := 1, -- Intermediate calculation
    number2 := 2 -- Intermediate calculation
RETURN
    number1, -- Exposed in results
    number3 := number1
            + number2 -- Exposed in results
;
Result
NUMBER1 BIGINTNUMBER3 BIGINT
13

NUMBER2 is used to compute NUMBER3 but doesn't appear in the output. This keeps query results focused on what consumers actually need.

Functions that must live in DEFINE

Some functions produce internal values that can't be returned directly:

Function typeWhy it can't be returnedWhat to return instead
INPUT()Declares a parameter placeholderThe bound values via BIND_XXX()
ENTITY()Declares an entityThe bound values of the INPUT() referencing the entity
SOURCE_XXX()Declares a connectionThe EXTERNAL_XXX() that uses the source
UDF()
MACRO()
Declares a functionThe function applied to concrete parameters

Definitions on this page are local to the query. To keep them across requests, see Create features .

Example

This example brings it all together: it defines an input with a data source, computes a derived feature, binds values, filters, sorts, and paginates.

FeatureQL
DEFINE
    -- ** Input definitions **
    customer_id := INPUT(BIGINT),
    -- ** Mapping to data source **
    dim_customers := INLINE_COLUMNS(
        customer_id BIGINT BIND TO customer_id,
        name VARCHAR
        FROM CSV(
            customer_id,name
            101,Alice
            102,Bob
            103,Charly
            104,Daniel
            105,Elody
            106,Francis
            107,George
            108,Henry
            109,Isaac
            110,Jack
        )
    ),
    -- ** Define pure transformations **
    name := dim_customers[name],
    name_length := LENGTH(name)
RETURN
    -- ** Features to evaluate and return **
    customer_id,
    name,
    name_length
FOR
    customer_id := BIND_VALUES(SEQUENCE(101, 106))
WHERE name < 'Henry'
ORDER BY name DESC
LIMIT 3
OFFSET 1
;
Result
CUSTOMER_ID BIGINTNAME VARCHARNAME_LENGTH BIGINT
105Elody5
104Daniel6
103Charly6

For every query modifier and pagination form, see the RETURN syntax reference . When a definition should outlive the query, see Create features .