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.

Anatomy of a query

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

Each clause has a specific role:

  • WITH defines features locally, on top of what already exists in the registry. Only features referenced by SELECT are actually evaluated — the rest are ignored.
  • SELECT lists the features to evaluate and return.
  • FROM pulls in persisted features from one or more namespaces.
  • FOR binds concrete values to the query's inputs. Without binding, a query with INPUT() features won't execute. See Binding inputs for details.
  • WHERE filters the result rows. You can reference any feature — including ones defined inline in the SELECT.
  • ORDER BY sorts the results. Supports ASC/DESC and NULLS FIRST/NULLS LAST.
  • LIMIT and OFFSET control pagination.

Note: GROUP BY and UNNEST are supported for analytics queries. See Grouping and unnesting for details.

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
WITH
    -- 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)
SELECT
    -- Features to evaluate and return
    CUSTOMER_ID,
    NAME,
    NAME_LENGTH
FOR
    CUSTOMER_ID := BIND_VALUES(@literal(SEQUENCE(101, 106))),
WHERE NAME < 'Henry'
ORDER BY NAME DESC
LIMIT 3 OFFSET 1
Result
CUSTOMER_ID BIGINTNAME VARCHARNAME_LENGTH BIGINT
105Elody5
104Daniel6
103Charly6

Last update at: 2026/03/03 16:47:38
Last updated: 2026-03-03 16:48:19