Skip to navigation

Filters and Operators

View as Markdown

PQL separates the entities to score from the historical context used to form a prediction.

  • FOR and the indices parameter select the entities for which to generate predictions.
  • WHERE filters the historical context.
  • ASSUMING conditions the prediction on a hypothetical attribute value.

Select entities

Specify an explicit key or list of keys in the query:

PREDICT COUNT(orders.*, 0, 30, days) > 0
FOR customers.customer_id IN (42, 57, 81)

For a programmatically generated list, pass the keys through materialize(indices=...):

from sdm_client import PredictiveQuery, SDMClient, KumoRelational
query = PredictiveQuery(
"PREDICT COUNT(orders.*, 0, 30, days) > 0 FOR EACH customers.customer_id",
schema,
)
request = query.materialize(indices=[42, 57, 81])
with SDMClient(url="http://localhost:8000") as client:
result = client.predict(request, model=KumoRelational())

indices overrides keys embedded in the query. A materialize() call accepts up to 100,000 keys, gathered as up to 100 NIM calls.

Filter which context examples qualify

A temporal WHERE clause selects which entity/anchor rows become labeled context examples; it does not remove individual historical events from the related tables, and it does not narrow explicitly scored indices:

PREDICT COUNT(orders.*, 0, 30, days) > 0
FOR customers.customer_id=42
WHERE COUNT(orders.*, -30, 0, days) > 0

The WHERE clause retains as context examples the entities that had at least one order during the 30 days before the anchor time.

Current Kumo Relational static column filters are limited to columns in the same table. Joined static filters described by broader PQL grammars are not supported by the current validator.

PREDICT customers.segment
FOR customers.customer_id=42
WHERE customers.region = "North America"

Combine conditions

Use AND, OR, and NOT with type-compatible expressions:

PREDICT SUM(orders.amount, 0, 30, days) > 100
OR COUNT(orders.*, 0, 30, days) > 10
FOR customers.customer_id=42
WHERE COUNT(orders.*, -90, 0, days) > 0

Start with one condition, and add other conditions only after the base query succeeds.

Set the anchor time

The anchor time defines “now” for temporal windows. Pass time controls to materialize():

import pandas as pd
request = query.materialize(
indices=[42, 57, 81],
anchor_time=pd.Timestamp("2025-01-01T00:00:00Z"),
)

An explicit historical anchor time is useful for backtesting. Ensure that both features and labels comply with the time boundary.

You can specify separate anchors for prediction and context:

request = query.materialize(
indices=[42, 57, 81],
anchor_time=pd.Timestamp("2025-06-01T00:00:00Z"),
context_anchor_time=pd.Timestamp("2025-03-01T00:00:00Z"),
)

Verify that the deployed SDK and NIM versions support the optional inference controls.

sdm-client automatically drops from the context any row that is a scored row itself, at the moment it answers the question being asked — with a warning naming how many rows were removed. You do not need to hand-craft WHERE and anchor-time logic solely to prevent that specific leak.

Condition with ASSUMING

PREDICT COUNT(orders.*, 0, 90, days) = 0
FOR customers.customer_id=42
ASSUMING customers.plan = "premium"

ASSUMING conditions the prediction on in-context examples that have the specified value. It does not estimate a causal treatment effect and must not be interpreted as proof that changing the attribute will cause the predicted outcome.

Use an assumed state only when it has adequate historical representation. Check the stability of the results across related cohorts, protect sensitive attributes, and do not use an assumed association as the sole basis for a high-stakes decision.