Prototyping with lazy evaluation
FeatureQL evaluates features lazily: only features referenced in the SELECT clause (and their dependencies) are computed. Everything else is ignored. This makes prototyping fast — you can define features for multiple entities in a single query and explore them one at a time by changing what you select.
Exploring one entity at a time
Consider a query that defines features for both customers and orders. When you select only customer-related outputs, FeatureQL evaluates just those features and their dependencies:
WITH
-- Related to the customer
CUSTOMER_NAME := TABLES.DIM_CUSTOMERS[name],
NUM_ORDERS_RELATED := RELATED(SUM(IF(ORDER_DATE>TIMESTAMP '2025-01-01', 1, 0)) GROUP BY TABLES.FCT_ORDERS[order_customer_id] VIA CUSTOMER_ID),
-- Related to the order
ORDER_DATE := TABLES.FCT_ORDERS[time_create]
SELECT
-- Related to the customer
CUSTOMER_ID,
NUM_ORDERS_RELATED,
-- Related to the order
-- ORDER_ID,
-- ORDER_DATE
FROM FM.ECOMM
FOR CROSS
CUSTOMER_ID := BIND_VALUES(SEQUENCE(100,102)),
ORDER_ID := BIND_VALUES(SEQUENCE(200,203)),
;| FM.ECOMM.CUSTOMER_ID BIGINT | NUM_ORDERS_RELATED VARCHAR |
|---|---|
| 100 | 2 |
| 101 | 0 |
| 102 | 1 |
The same query, with order-related outputs selected instead, evaluates only the order features:
WITH
-- Related to the customer
CUSTOMER_NAME := TABLES.DIM_CUSTOMERS[name],
NUM_ORDERS_RELATED := RELATED(SUM(IF(ORDER_DATE>TIMESTAMP '2025-01-01', 1, 0)) GROUP BY TABLES.FCT_ORDERS[order_customer_id] VIA CUSTOMER_ID),
-- Related to the order
ORDER_DATE := TABLES.FCT_ORDERS[time_create]
SELECT
-- Related to the customer
-- CUSTOMER_ID,
-- NUM_ORDERS_RELATED,
-- Related to the order
ORDER_ID,
ORDER_DATE
FROM FM.ECOMM
FOR CROSS
CUSTOMER_ID := BIND_VALUES(SEQUENCE(100,102)),
ORDER_ID := BIND_VALUES(SEQUENCE(200,203)),
;| FM.ECOMM.ORDER_ID BIGINT | ORDER_DATE VARCHAR |
|---|---|
| 200 | 2025-09-18T14:30:00 |
| 201 | 2024-12-08T09:45:00 |
| 202 | 2025-02-03T12:00:02 |
| 203 | 2025-09-18T14:30:00 |
The definitions are identical in both cases — only the SELECT clause changes. This lets you iterate quickly: define everything you might need, then toggle outputs to explore different slices of the data.
Cleaning up after prototyping
Once you've settled on the features you need, remove unused definitions for clarity. A production query should only contain features that contribute to its output — leftover definitions add noise even though they don't affect performance.
If you select features from multiple entities in the same query (e.g., both customer and order outputs), FeatureQL produces a cross-join between the entity key sets. This is rarely what you want. Keep each query focused on a single entity's outputs, and use RELATED() or EXTEND() to pull in data from other entities.