Skip to main content
On this page

Model Fields

Filters and parameters

Let readers narrow a workspace or query with named filters, and keep fixed rules always on.

Audience
Data teams
Prerequisites
  • A workspace root or query you can edit

Filters decide which rows count. An optional filter is one a reader can switch on, with a value they supply through a parameter. A required filter is a fixed rule that always applies. Both are named, labelled and written in the model’s SQL, so the filter bar, the CLI and agents all read the same thing.

Three kinds of filter

Written asWhereParametersApplies
OPTIONAL_FILTER('name', predicate, label='…')Workspace roots and queriesAny, or noneWhen a reader or a run switches it on
REQUIRED_FILTER('name', predicate, label='…')Kater datasets, semantic models, workspace roots and queriesNoneAlways
A plain WHERE KATER__… conditionShared modelsNoneAlways

Example

The Ad Reporting workspace root gives every query two optional filters: a reporting window in months and a list of campaigns. This is Snowflake, so parameters are written :name.

workspaces/ad_reporting/workspace.sql
---
name: ad_reporting
model_type: workspace
label: Ad Reporting
parameters:
- name: reporting_date
label: Reporting Date
kater_data_type: number
default_value: 12
- name: campaign_name
label: Campaign Name
kater_data_type: string
subtype: multiselect
allowed_values:
from_field:
ref: union__campaign_name
---
SELECT
*
FROM semantic.ad_reporting
WHERE
OPTIONAL_FILTER(
'reporting_date',
KATER__IS_WITHIN_LAST(union__date_day, :reporting_date, 'month', complete => TRUE),
label='Reporting Date'
)
AND OPTIONAL_FILTER(
'campaign_name',
KATER__IS_ONE_OF(union__campaign_name, :campaign_name),
label='Campaign Name'
)

A query can add its own. This one, on DuckDB, writes parameters as $name, and holds a fixed rule too:

workspaces/shop/query_contracts/region_mix.sql
WHERE
OPTIONAL_FILTER(
'is_equal_to__country',
KATER__IS_EQUAL_TO(shop.country, $is_equal_to__country),
label='Country'
)
AND REQUIRED_FILTER(
'text_contains_paid__channel',
KATER__TEXT_CONTAINS(shop.channel, 'paid'),
label='Channel contains paid'
)

Filter rules

  • Filters sit at the top of WHERE. Each is a direct AND condition of WHERE. Not under OR or NOT, and not in HAVING, QUALIFY, a join or a CASE.
  • The label is the third argument. Write label='Region'. Description and AI context go in -- @description and -- @ai_context comments directly above the filter.
  • Names say what the filter does. The convention is <condition>__<field>, such as is_one_of__region. A filter’s parameter shares its name.
  • A required filter takes no parameters. Even a parameter with a default makes it invalid.
  • A default never switches a filter on. It only supplies a value when the filter is on.
  • Every query reads the root’s filters. A query inherits the filters and parameters of its workspace root and of the queries it reads.
  • Filters on a measure stay in their query. A workspace filter applies before grouping, so a filter after grouping belongs to the query that groups.

Parameters

A parameter is a value a reader supplies. Only workspace roots and queries declare them, in the frontmatter’s parameters: list. A root’s parameters are shared by every query in the workspace, so a query can read :reporting_date without declaring it again.

Write a parameter as your warehouse’s own placeholder: :name on Snowflake and $name on DuckDB. Each save and each compile adds an entry for every parameter the SQL reads that has none. Edit the entry to add a label, a default or a list of choices.

KeyWhat it doesExample
nameRequired. Lower snake case. Matches the placeholder.reporting_date
kater_data_typestring, number, boolean, date, time or timestamp. Inferred when left out.number
subtypesingle_value, range or multiselect. Inferred when left out. A range is for numbers, dates and times.multiselect
default_valueUsed when a reader gives no value. A list of two for a range, a list for a multiselect.12
min, maxInclusive bounds, from a fixed value (from_value) or a field’s minimum or maximum (from_field: {ref: …}).min: {from_value: 0}
allowed_valuesThe choices: a fixed list (from_list), or a field’s distinct values (from_field, with an optional limit that defaults to 100). Not for ranges.from_field: {ref: union__campaign_name}
relativeLets a reader supply a period, such as the last 3 months, as well as fixed dates.true
label, description, ai_contextThe name readers see, a sentence for people, and guidance for agents.label: Campaign Name
SubtypeWritten in SQL asValue
single_valueKATER__IS_EQUAL_TO(region, :region)One value
rangeKATER__IS_BETWEEN(order_date, :period)Two ordered ends
multiselectKATER__IS_ONE_OF(region, :regions)A list with at least one value

Parameters cannot go in CASE, IF or IFF conditions, HAVING, QUALIFY, a join’s ON, or an EVAL SET. A parameter used outside a filter, such as a target in arithmetic, is always needed unless it has a default.

How a run uses them

SituationResult
An optional filter is offIt does not apply, and its parameter is not needed.
It is on, with a value or a defaultIt applies.
It is on, with no value and no defaultAn input error, before anything runs on the warehouse.
A value is not valid, even for a filter that is offAn input error. Every value given is checked.
A required filterAlways applies. It needs no switch.

A run switches filters on by name. From a terminal, pass them in a file keyed by each model’s id from kater model list:

Terminal window
kater run --select connections/duckdb_sample/workspaces/shop/query_contracts/region_mix.sql --inputs-file inputs.json

A workspace keeps its saved values and selected filters in default-inputs.json, in the same shape:

workspaces/ga4_page_facts/default-inputs.json
{
"rel1_6FpTma5qXPUnVtX3wWYGQ60uwp9UFBA9xboZqQw3IRM": {
"parameters": {
"last_n_days": 30
},
"filters": [
"event_date_dt_last_n_days"
]
}
}

The filter bar in the editor

In the workspace editor, the filter bar is one row of pills under the query’s toolbar. Filters in the toolbar hides it or shows it. The pills come in two groups, each led by its mark:

  • Workspace. The root’s filters as pills, such as “Session Start Date is within the last 30 days”. A filter that is off is dashed and faded, with a ring. A filter that is on is solid, with a dot, and the rows follow it. Click the dot or the ring to turn the filter off or on. Those that do not fit wait under N more.
  • A parameter no filter reads shows as a parameter pill, with its name and value.
  • This query. The query’s own filters, a date range among them, its top rows, and its row limit.
  • + Filter. Filter by a field, Top rows by a measure, Row limit and Custom filter, each a form in the same popover.

Click a workspace pill to change it in place. Its popover names the filter and where it comes from, such as “Marketing Sessions filter bar”, then the switch, the condition and a control for the value. Edit in SQL editor at its end opens the SQL that writes the filter.

The popover of the Device Category pill, opened from the list under 6 more: Device categories, Marketing Sessions filter bar, the switch off, is one of, Select device categories, and Edit in SQL editor
A workspace filter’s popover.
The Ad Reporting filter bar with Reporting Date is within the last 12 complete months on, with its dot, and Campaign Name is one of (any) off, dashed with a ring, over the rows of spend_by_platform
A filter that is on has a dot, and the rows follow it. A filter that is off is dashed, with a ring.

A query pill’s popover has Applied, the condition’s form, Move to workspace, and Remove filter. Move to workspace moves the pill to the Workspace section of the filter bar, where it applies to every query in the workspace. A query whose SQL you wrote by hand shows a lock after its filters, which says why on hover.

Filters on the workspace overview

The overview’s Workspace filters section shows each root filter as a card, with its switch, condition and value. Drag a card by its grip to change the order.

Edit a filter and its parameter

Select a card’s … to open its settings. One form edits the filter and the parameter it reads together:

  • Filter. Label, Description and AI context.
  • Its parameter. Name, Label, Type, Default and Values from. The name is read only, because the SQL reads the parameter by that name.
  • Remove filter takes the filter out of the root.
The settings of the Lookback window filter: Label, Description and AI context, then Its parameter with Name lookback_days and a lock, Remove filter and Save
A filter card’s settings edit the filter and its parameter.

Add a filter or a parameter

Select Add beside Workspace filters:

  • Filter with a value to pick (Parameterized): a filter whose value the reader sets, through a parameter.
  • Filter that always applies (Static): a condition with no value to pick.
  • Parameter: a value with no filter, such as a target that a query reads in a calculation.
The Add menu open over the filter cards: Filter with a value to pick, Parameterized; Filter that always applies, Static; Parameter
Add a filter or parameter.

Parameters

The Parameters section lists only the parameters no filter reads, with their type, where their values come from, their default and their value. A filter’s own parameter is edited from that filter’s card. A parameter the frontmatter declares that no SQL reads yet is listed too, with Remove. A missing default reads null.

More › Show SQL parameter names shows each parameter’s SQL name. More › Reset filters to defaults puts every filter and value back to the saved defaults.

Add filters without writing SQL

  • The filter bar. Select + Filter, then Filter by a field, a field and a condition. Edit › Add filter opens the same form.
  • The field menu. A field’s Filters opens with Workspace, selected first, for a filter every query can switch on, and This query, for the open query alone. A measure offers only This query.
  • The workspace overview. Add beside Workspace filters.
  • The terminal. kater model edit MODEL --path FILE --workspace-inputs-file edits.json takes add_custom_filter, update_filter, remove_filter, reorder_filters and update_parameter. add_custom_filter takes a condition no menu offers, such as clicks > conversions, and the writer wraps it in the filter call.

Common errors

CodeCauseFix
parameterized_required_filterA REQUIRED_FILTER reads a parameter.Make it an OPTIONAL_FILTER, or write the value in.
parameter_not_allowedA parameter in a shared model, or a parameter a chart declares.Move the filter to the workspace root or a query. A chart’s filter reads a parameter of its query.
chart_parameter_unknownA chart’s filter reads a parameter that its query does not have.Read a parameter of the chart’s query, or write the value in.
chart_parameter_not_singleA chart’s filter reads a parameter that holds a list or a range.Read a parameter that holds one value, or write the values in.
filter_not_allowedAn OPTIONAL_FILTER in a shared model.Move it to the workspace root.
filter_label_directive-- @label above a filter.Write label='…' in the call.
invalid_filter_argumentsA third argument that is not label='…'.Use the form label='Region'.
conflicting_filter_metadataTwo filters with one name give different labels or descriptions.Make them agree, or rename one.
undeclared_parameterInformation. The SQL reads a parameter with no entry yet.Save or compile, or apply the fix that declares it.
unused_parameter_entryWarning. A query declares a parameter nothing reads.Apply the fix that removes the entry.