Skip to main content
On this page

Model Fields

Fields

Every field is a dimension, a measure or a custom calculation. Know which one you need, how to declare it and where to add it.

Audience
Data teams
Prerequisites
  • A model you can edit

Every field in Kater is a dimension, a measure or a custom calculation. A dimension is a value to group or filter by. A measure is a recipe for a total, which each reader works out again at its own grouping. A custom calculation is a value worked out over a query’s result rows, such as a rank. Declare a field once, and every query, app and agent reads it by its name.

Three kinds of field

KindWhat it isExampleWhereRead more
DimensionA value per row, to group or filter by.Region, Order Month, Amount BandEvery modelDimensions
MeasureA reusable aggregate. A reader totals it again from the source rows, at the reader’s own grouping.Revenue, Orders, CustomersDatasets, semantic models, workspace roots, queriesMeasures
Custom calculationA value worked out over a query’s result rows, such as a rank or a running total.Orders (Rank)Queries, tests and the SandboxCustom calculations

How the three kinds differ

This query of the sample shop has one field of each kind. Region is a dimension, Orders is a measure, and Orders (Rank) is a custom calculation:

workspaces/shop/query_contracts/region_rank.sql
SELECT
shop.region,
shop.count_distinct__order_id,
CUSTOM_CALCULATION(
'rank__count_distinct__order_id',
KATER__RANK(shop.count_distinct__order_id, 'desc') OVER ()
) AS "Orders (Rank)"
FROM workspace.shop AS shop
GROUP BY
shop.region
ORDER BY
3
RegionOrdersOrders (Rank)
EMEA7771
LATAM7602
AMER7283
APAC6714
null645

Each kind behaves in its own way when another model reads this query:

  • Region stays a value. A reader groups or filters by it.
  • Orders stays a recipe. The query passes the measure through, so a reader that shows Orders with no grouping counts the orders again from the order rows. It never adds up these five rows.
  • Orders (Rank) stays a finished value. The rank was worked out over these five rows. A reader gets 1 to 5 as they are, and cannot work the rank out again at its own grouping.

Which kind do you need?

You wantUseExample
A value to group or filter byA dimensionRegion, Order Month
A date by month, or the day of the weekA date grain or partOrder Month, Order Date Day Name
Values sorted into readable groupsA map, a bucket or a flagRegion Group, Amount Band
A total that stays right at any groupingA measureRevenue, Orders, Customers
A ratio that stays right at any groupingA measure built from measuresRevenue per Customer
A grand total, another member or another period beside each rowA measure with EVALThe share of all orders
A value that depends on the order or position of the result rowsA custom calculationA rank, a running total, the row before
A comparison with another calendar periodA period comparisonOrders against the previous month

The formula decides the kind, not the wrapper. A formula with no aggregate and no measure inside it is a dimension. A window is never a measure. A wrapper that disagrees with its formula gets a warning, and a fix that swaps it.

Declare a field

modeling/kater_objects/datasets/orders.sql
-- @description Order amount before discounts.
-- @format currency(currency, 2)
MEASURE('sum__amount', KATER__SUM(orders.amount), NOT_ADDITIVE_ACROSS(currency)) AS "Revenue",
PartWhat it doesExample
DIMENSION or MEASUREThe declaration. In a query, CUSTOM_CALCULATION too.MEASURE(...)
First argumentThe field name, and its identity. Other models read it by this name. By convention, lower snake case.'sum__amount'
Second argumentThe formula. The formula decides the kind of field, not the wrapper.KATER__SUM(orders.amount)
NOT_ADDITIVE_ACROSS(...)Measures only, last argument. The dimensions the measure cannot be added up across. See Measures you cannot add up.NOT_ADDITIVE_ACROSS(currency)
AS "Label"The display label. Optional. Changing it changes nothing that reads the field.AS "Revenue"
-- @ directives above itDescription, format, AI context and more. See Formats, descriptions and AI context.-- @format number(0)
  • Declarations are outermost. A DIMENSION, MEASURE or CUSTOM_CALCULATION sits in the final SELECT, never inside a CTE, a subquery or a union branch.
  • A new field needs a new name. It cannot take the name of any field in scope, from any model the SELECT reads, in any letter case.
  • A field you read keeps its name. shop.region or shop.sum__amount on its own passes the source’s field through. See Pass through, evaluate or declare.

Names, labels and identity

  • The name is the field’s identity. Queries, apps, tests and agents read a field by its name, so it never changes by accident.
  • The label is for people. Change it freely. Nothing that reads the field changes.
  • See how a field is computed. The Definitions view shows a card per field, and kater model explain FIELD --relation semantic.shop prints it.
  • Find what reads a field. kater references FIELD --relation semantic.shop.
  • Rename through the menu. Rename in the field menu updates references in the same model. A model elsewhere that reads the field blocks it.

Fields in the Shared models editor

In a semantic model or Kater dataset, you add, change and describe fields without writing SQL. Each change writes the SQL shown on these pages.

The field list

The Fields tab of the sidebar groups fields by the source they come from.

  • A folder per source. Each shows the source’s label and alias, and how many of its fields are in the model. The base comes first and says Base. The order matches the workspace’s field picker for the same model.
  • Ticks. A ticked field is in the model. Tick a field to pass it through, and untick it to take it out. ⌘Z undoes either.
  • Made here. A field this model declares says Made here.
  • Not in the model. Under each folder, the source’s other fields wait unticked.
  • Measures are blue. Wherever a field is named, a measure’s name is blue. A dimension’s mark says what it is.
  • Search and add. Search fields (/) finds a field. The + beside it makes a new field, and Add source after the folders adds a source.

In a Kater dataset, the table’s columns are locked in, and fields you add show under Made in this dataset. See Kater datasets.

The field panel

Click a field to open its panel. It shows where the field comes from, the source and then the field, and an In the model switch. Then you edit:

  • Label and Name. A field whose label is still its SQL name says No label.
  • Computes, for a field made here: its formula.
  • Description and AI context.
  • Format and Values, each Automatic until you set it.
  • Tags and Business questions.

Show in SQL opens the SQL pane at the field. Delete field removes a field made here. A field passed through from a source offers Take out of the model in its place.

The first_seen_month field selected: its panel shows No label, Made here, From GA4 Client Lifecycle, First Seen Start Date, In the model switched on, First Seen Month being typed as the Label, Name first_seen_month, Computes KATER__MONTH(lifecycle.first_seen_start_date), Description, AI context, Format and Values on Automatic, Tags, Business questions, Show in SQL and Delete field
A field’s panel.

The field menu

Right-click a field in the list, or a column in Rows. The menu names the field, its source and its expression, with Search operations under them.

GroupItems
The fieldSettings (Enter) opens the field panel. Rename, Format and Values.
Make a new field from itAggregations, Derive, Timeframe and Windows.
The modelAlways filter adds a filter that always applies. Preview sample, Show in SQL and Show in Files.
LastTake out of the model.
The menu on First Seen Start Date: the field, GA4 Client Lifecycle lifecycle, lifecycle.first_seen_start_date, Search operations, Settings with Enter, Rename, Format, Values Automatic, then Make a new field from it with Aggregations, Derive, Timeframe and Windows, then Always filter, Preview sample and Show in SQL
A field’s menu in a model.

A new field from an operation

An operation under Make a new field from it, or the + beside Search fields, opens the new-field dialog. Select Measure or Dimension, and Prompt AI or Manual. On Manual:

  1. Start with. The field the new one reads, such as Session Start Date.
  2. Turn it into. What to make of it, such as Day of week.
  3. Settings. Options for that operation, when it has any.
  4. Name it. Optional: Name, SQL name and Description.

The dialog shows the Kater SQL it writes, a preview of the new field’s values and its definition. Select Add to the model.

The New dimension dialog on Manual: Kater SQL DIMENSION('day_name__session_start_date', KATER__DAY_OF_WEEK(sessions.session_start_date)), Start with Session Start Date, Turn it into Day of week, Settings Short day names, Label Session Start Date Day Name and SQL name day_name__session_start_date, a preview of sessions by day from Fri 2,931 to Sun 2,323, and Preview, Cancel and Add to the model
A new field from an operation.

The Fields sheet

Select Fields above the grid. The sheet has one row per field: Field (its mark and label), Name, Source (the alias), Description, Format, Values and AI context. Click a cell to edit it in place. Paste a column, such as twelve descriptions, and it saves as one change. The header counts the fields with no label, and Write labels with Ask opens Ask with a prompt for your agent that lists them.

The Fields sheet of Marketing Sessions: 60 fields, 21 with no label, Write labels with Ask, and the columns Field, Name, Source, Description and Format. Fields with no label say No label, and a description is being typed for session_source_medium
The Fields sheet.

Add fields without writing SQL

  • In a shared model. Use the field list, the field menu and the new-field dialog above. New › Field and Edit › Add field open the same dialog.
  • In a workspace query. Right-click a field in the field list. Its categories are Filters, Sort, Aggregations, Windows, Compare with, Derive, Calculate at, Timeframe, Format and Edit. Each offers only what fits that field and that model. File › New › Field opens New measure, New dimension, New calculation or New filter. See Queries.
  • The terminal. kater new field --path QUERY.sql walks the same steps for a query. kater model edit changes any model.
  • Your agent. Ask in words. It shows you the field and saves it after your yes.
Terminal window
kater new field --path QUERY.sql --kind calculation --from sum__spend \
--make previous_period --set output=percent_change --write

Operations name what they add, such as sum__amount or count__status, with a label such as “Status (Count)”. They also write a format: a count gets number(0) and a share of total gets percent(1).

Common errors

These apply to every kind of field. Each kind’s page lists its own.

CodeCauseFix
field_name_in_scopeThe new name is already a field in scope.Pass the source field through, or rename the new one.
measure_requires_aggregation_or_evaluationA MEASURE aggregates nothing.Aggregate it, or apply the fix that declares a DIMENSION. See Measures.
measure_over_windowA MEASURE over a window, such as RANK() OVER (...).Use CUSTOM_CALCULATION in a query, or DIMENSION in a shared model. See Custom calculations.
unnamed_outputHint. An output with no declaration, which no other model can read.Apply the fix that names it. See Dimensions.

Next steps