Skip to content

Business question YAML reference

11 min read · Updated 29 Oct 2026

This is the reference for Business Questions in Semantic Layer V3 (fileVersion: 3). YAML and JSON represent the same document. Business Questions must be enabled in your environment; a document version does not enable a feature or publish a semantic layer. Use the Business questions guide for editor and MCP workflows.

The properties below describe the implemented contract. Conditional coloring and the additional nested variants listed under availability are not part of this contract.

This synthetic model defines all references used by its questions. Replace the table and column sources with your own data. The first question accumulates revenue within each region, compares those completed values across regions for each month, and calculates an additional result formula. Hidden selections still define the calculation; output controls only the returned columns.

fileVersion: 3
name: Sales analysis
views:
Sales:
source: { type: table, table: SALES }
fields:
Date: { source: SALE_DATE, dataType: date }
Region: { source: REGION, dataType: string }
Amount: { source: AMOUNT, dataType: float }
joins: []
dimensions:
Region:
kind: field
resultType: string
reference: { view: Sales, field: Region }
Month:
kind: field
resultType: date
reference: { view: Sales, field: Date }
dateLevel: month
measures:
Revenue:
resultType: float
expression: '{m1}'
m1:
aggregate: SUM
arguments: [{ reference: { view: Sales, field: Amount } }]
udfs: {}
layout: {}
businessQuestions:
Regional running share:
question: How does each region contribute to accumulated revenue?
description: Monthly regional contributions.
meaning: Monthly revenue accumulated separately within each region.
businessValue: Compare the regional contribution as the year progresses.
categories: [sales, trend]
followUps: [Regional revenue]
dimensions:
- { key: month, reference: { dimension: Month } }
- { key: region, reference: { dimension: Region } }
measures:
- { key: current, reference: { measure: Revenue } }
- key: cumulative
reference: { measure: Revenue }
advancedCalculation:
runningTotal:
aggregate: SUM
orderBy: [{ reference: { dimension: month }, direction: ascending }]
partitionBy: [{ reference: { dimension: region } }]
- key: share
reference: { measure: Revenue }
advancedCalculation:
runningTotal:
aggregate: SUM
orderBy: [{ reference: { dimension: month }, direction: ascending }]
partitionBy: [{ reference: { dimension: region } }]
compareToTotal:
comparison: ratio
aggregate: SUM
partitionBy: [{ reference: { dimension: month } }]
- key: earlierShare
expression: '({accumulated} - {currentValue}) / {accumulated}'
accumulated: { reference: { measure: cumulative } }
currentValue: { reference: { measure: current } }
format: { pattern: '0.00%' }
filters:
expression: '{regionChoice}'
regionChoice:
operator: equals
arguments:
- reference: { dimension: Region }
- reference: { parameter: selectedRegion }
parameters:
selectedRegion: { dataType: string, default: East }
resultFilters:
expression: '{minimumShare}'
minimumShare:
operator: greaterThan
arguments:
- reference: { measure: share }
- reference: { parameter: minimum }
parameters:
minimum: { dataType: float, default: 0 }
orderBy:
- reference: { dimension: month }
direction: ascending
- reference: { measure: share }
direction: descending
output:
- reference: { dimension: month }
- reference: { dimension: region }
- reference: { measure: share }
- reference: { measure: earlierShare }
preferredCharts:
- { type: table, reason: Compare exact monthly values. }
Regional revenue:
dimensions:
- { key: region, reference: { dimension: Region } }
measures:
- { key: revenue, reference: { measure: Revenue } }
defaults:
topN: 10
ranking: { reference: { measure: revenue }, direction: descending }
hideZeroValues: true
showOthers: true
othersPosition: last
othersLabel: Other regions
orderBy:
- reference: { dimension: region }
direction: ascending

An ordinary filter on Region also limits the rows used to calculate the share. Remove that filter when you want every region in the denominator. Hiding a region column does not remove that region from the calculation.

A saved question is a named entry under businessQuestions. Its key is its identity; id and title in discovery responses are not additional stored YAML properties.

Property Shape and meaning
question Optional wording of the question, when different from its map key.
description Optional short explanation.
meaning Optional description of grain, time window and exclusions.
businessValue Optional explanation of the decision the answer supports.
categories Optional list of free-text discovery categories.
followUps Optional names of other questions in this layer. No self-reference. Save the target first or in the same authoring batch. Authoring reports unresolved names it drops.
dimensions Grouping selections, as an ordered list. Its order is the column order. Use an empty list for a scalar answer.
measures Measure selections, as an ordered list. May be empty for a distinct-value list. At least one dimension or measure is required.
filters Ordinary conditions evaluated before calculation.
associativeFilters Membership conditions on related records.
resultFilters Conditions on calculated results.
orderBy Ordered list of final sort references and optional directions.
output Optional nonempty ordered projection of selected columns.
preferredCharts Ranked suggestions containing type and optional reason.
defaults Optional ranking, row suppression and Others settings.

Unknown properties are rejected. For example, the question has no calculatedMeasures, transformations, sorting, conditionalColoring, or generic engine-options container.

dimensions and measures are ordered lists. Give each entry a key when anything refers to it by name: calculations, and repeated uses of the same reusable entity. A key is a local identity, not a generated engine index, and can differ from the reusable entity it selects. A list keys every entry or none.

A plain measure reference keeps its inferred result type when selection keys are omitted.

Order matters. It is the answer’s default column order, a moving calculation runs along the first dimension, and a row comparison partitions by the last. A name-keyed map of selections is still read, in the order its keys are received, but a map’s key order is not kept once it is stored. New documents use lists; use a list whenever selection order matters.

Reference location What the name identifies
Dimension selection reference.dimension A reusable semantic dimension.
Dimension selection reference: {view, field} A field in the semantic layer.
Ordinary measure selection reference.measure A reusable semantic measure.
Result-formula operand reference.measure A sibling measure selection in this question, including forward references. No fallback to reusable names.
resultFilters measure reference with keyed measures A completed sibling selection.
resultFilters measure reference with unkeyed measures A reusable semantic measure.
orderBy, output, defaults.ranking, defaults.rankedDimension Selection keys for keyed lists; reusable names for unkeyed ones.
Calculation dimension references with keyed dimensions Dimension selection keys in this question. With unkeyed dimensions, use the selected global dimension names.
periodComparison, periodAxis or partitionBy naming no key A stored Time Axis the question does not select, by its layer name. A key with the same name wins.
Ordinary and associative filter field/dimension references Semantic-layer fields or reusable dimensions, not selection aliases.

A comparison over a stored Time Axis the question does not select compares one window with another across the whole answer, as a stored measure on that axis does: last30Days against the 30 days before gives one row per segment, not one per segment and day. A partitionBy naming that axis partitions by nothing, because the answer holds a single period. An orderBy inside a calculation still needs a selected key, since it runs along the answer’s rows.

Unkeyed entries have the form - reference: {dimension: Region}, - reference: {view: Sales, field: Region}, or - reference: {measure: Revenue}, and carry references only. Key the list to attach calculations or define a result formula: - {key: revenue, reference: {measure: Revenue}}. Selection order defines calculation grain and the default column order. The analytical selection limit is 20 dimensions plus measures; plain hidden filter-only dependencies are excluded from that limit.

A keyed dimension contains either reference or an inline periodAxis, never both. A keyed reference measure can additionally contain periodAxis, periodComparison, nestedCalculation and advancedCalculation, subject to their compatibility rules, and a format: {pattern: ...} that replaces the stored measure’s format for that selection: - {key: share, reference: {measure: Revenue}, format: {pattern: "0.0%"}}. Selection-level labels are not accepted on reference selections; reuse the referenced entity’s metadata. A result formula can contain its own format: {pattern: ...}.

Calculation partitionBy and currentPartitionBy values are flat lists of dimension references, for example [{reference: {dimension: region}}]. Do not wrap that list in another list; the same shape applies to a series calculation’s partitionBy.

An ordinary or result filter contains expression, optional parameters, and named condition blocks. Expressions combine {condition names} using AND, OR and parentheses. Each condition appears exactly once. Names such as f1 are generated conveniences; custom names are preserved. Names cannot be blank or contain braces or line breaks. expression and parameters are reserved.

Each condition contains operator and ordered arguments. Subjects use reference; literal arguments use value with optional dataType; parameter arguments use reference.parameter. Declare defaults as parameters.<name>: {dataType: ..., default: ...} on that filter. Date values use semantic text, for example {value: '2026-09-25', dataType: date}. Relative-date arguments and filter-only date/bucket transforms reuse the semantic filter contract described in Semantic layer workflows and Period axes.

Ordinary conditions accept fields and ordinary dimensions as subjects. Result conditions also accept completed measures. Operators include comparisons (equals, notEquals, greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual), ranges (between, notBetween), lists (inList, notInList), presence (set, notSet), text matching and supported geography tests. Choose an operator supported by the subject’s datatype; invalid types and arities are rejected. Null, empty text, 0 and false have distinct meanings.

associativeFilters contains a target reference: {view, field}, an outer expression and named branches. Each branch owns filters and may specify via, an existing correlation-root view. The target field preserves the editor selection; membership is of its view, not the field’s value. Each filter slot accepts inline content or reference: { filter: name }. Use a regular definition in filters or resultFilters, and an associative definition in associativeFilters. Branch filters also accept regular references. The root filters collection stores the named bodies, without a type discriminator.

Ordinary question filters stay outside the membership branches. Put a condition inside a branch when it must restrict membership.

The supported outer shape is one intersection group followed by union branches: ({buyers} AND NOT {returns}) OR {priority}. Individual branches may use NOT; group-wide NOT, multiple intersection groups joined by OR, and AND over OR groups are rejected. Branch filters retain nested AND/OR support. A branch applies its row conditions first, then its measure conditions, joined by a top-level AND; measure conditions may be grouped among themselves but never with row conditions; see Measure filters in a set. Association names obey the condition name rules, with reference and expression reserved. See Associative filters for complete multi-table examples and correlation requirements.

This additional question uses the Sales model above:

businessQuestions:
Regions with large sales:
dimensions:
- { key: region, reference: { dimension: Region } }
measures:
- { key: revenue, reference: { measure: Revenue } }
associativeFilters:
reference: { view: Sales, field: Region }
expression: '{largeSales}'
largeSales:
filters:
expression: '{amount}'
amount:
operator: greaterThan
arguments:
- reference: { view: Sales, field: Amount }
- reference: { parameter: threshold }
parameters:
threshold: { dataType: float, default: 1000 }

Overrides are outside the saved question: parameters.measures[selection][parameter], parameters.filters[parameter], parameters.resultFilters[parameter], and parameters.associativeFilters[branch][parameter]. Omitted values use declared defaults. Unknown names and incompatible JSON scalar types are errors. Overrides do not rewrite defaults. A measure-reference selection can redeclare inherited parameters in its own parameters map. Those defaults apply without execution overrides; overriding one name retains the other selection defaults. Use parameters.drillLevels[selection] to choose a published drill-through level by field or dimension reference; omission chooses its first level. Unkeyed selections use their string index. See execution examples, including timestamp and SQL-list parameter restrictions.

An inline periodAxis dimension contains sources, period, level, and optional periodEnd. sources is a nonempty list of date/timestamp field or ordinary field-dimension references, with at most one source per view. level is year, quarter, month, week or day. period is a supported named window, {kind: relativeValue, unit, offset}, or {kind: relativeRange, unit, from, to}. Relative offsets are safe integers and from <= to. periodEnd: today | yesterday | latest | fixed sets the date the period is read as of: yesterday applies to to-date and trailing windows, latest to any named period, and fixed to any period with periodEndDate: YYYY-MM-DD, which it requires and no other end accepts. The period reference lists named windows and compatibility restrictions.

A measure’s periodAxis binding contains a dimension reference and optional period, level, periodEnd, periodEndDate, comparisonPeriod and comparisonOffset. Omitted window settings inherit the axis. The comparison offset defaults to -1; it is a signed calendar-baseline offset, not a row offset. Comparison baseline settings require an enabled comparison.

periodComparison contains type: current | value | diff | ratio | growth, its axis reference, optional alignment: calendar | weekday, and optional additionalDimensions. Each scope entry contains a dimension reference and optional period and level. Scope is not an extra reduction.

nestedCalculation contains aggregate: SUM | AVG | MIN | MAX and dimensions, in one of two forms that cannot be mixed:

  • A grain: dimensions names one or more stored dimensions. The measure is computed per combination of them, then aggregate reduces those values to each answer row. The dimensions need not be selected by the question. In a keyed question, a name is the key of a dimension the question selects, or else a stored dimension; a name that is both, for two different dimensions, is refused. Time axes, drill-through and set-filter dimensions cannot set a grain. A grain wraps the selection’s period comparison, if any, and an advancedCalculation runs over the reduced values.
  • A reduction along time: dimensions holds exactly one period-axis reference, with an optional inner periodAxis binding. It computes at that axis grain and then reduces the values. The inner binding and outer binding remain distinct; all axis references for one calculation must agree.

Nested percentiles and nested ratios are not available.

businessQuestions:
Typical region by month:
dimensions:
- key: month
reference: { dimension: Month }
measures:
- key: averageRegionRevenue
reference: { measure: Revenue }
nestedCalculation:
aggregate: AVG
dimensions:
- reference: { dimension: Region }
businessQuestions:
Monthly growth:
dimensions:
- key: month
periodAxis:
sources: [{ reference: { view: Sales, field: Date } }]
period: currentYear
level: month
measures:
- { key: revenue, reference: { measure: Revenue } }
- key: growth
reference: { measure: Revenue }
periodAxis:
reference: { dimension: month }
comparisonPeriod: year
periodComparison:
type: growth
reference: { dimension: month }
orderBy: [{ reference: { dimension: month }, direction: ascending }]

For an index against a fixed baseline, see grouped reducer formulas. They apply a scalar formula to completed grouped values before a total or comparison reducer.

advancedCalculation is a map of named blocks. Choose at most one primary calculation, at most one group operation, then an optional seriesValue. Execution always follows that order, regardless of property order. Omit unused blocks; {type: ...}, none, empty configurations and conflicting families are invalid new authoring.

Block Required settings Optional settings and behavior
movingCalculation aggregate, integer windowBegin, integer windowEnd showIfNotEnoughValues. Bounds are inclusive row offsets, with begin no greater than end. The first dimension is the moving axis; subsequent dimensions partition it. Uses effective question ordering.
runningTotal aggregate, nonempty orderBy, partitionBy Accumulate within each partition using the complete private ordering list. An empty partition list spans the answer with one dimension; over several, name the partition.
runningRate Same as runningTotal Running ratio using the chosen aggregate.
rank None ({} is valid) direction, dense, partitionBy. Ranks the selected measure within the chosen groups.
interRecord `comparison: value diff
total Exactly one reducer Optional partitionBy groups the completed values being reduced.
compareToTotal `comparison: diff ratio
seriesValue `select: first last`

aggregate is SUM, AVG, MIN or MAX. Order entries contain a dimension reference and optional direction: ascending | descending. Partition entries contain only a dimension reference. Referenced dimensions must be selected, including hidden dependencies. Duplicate references in one ordering or partition list are invalid. Moving and inter-record operations do not accept private orderBy or partitionBy settings.

Group operations choose exactly one of:

  • aggregate: SUM | AVG | MIN | MAX;
  • percentile: {value: 0.95, method: continuous | discrete, approximate: false}, with value from 0 to 1; omit approximate for exact calculation;
  • controlValue: {standardDeviations: 2}, the mean plus a finite multiple of sample standard deviation.

compareToTotal with controlValue accepts only comparison: diff; ratio and growth are refused.

Database support still determines whether a statistical operation can execute. A moving full-window requirement counts non-null values. Totals retain the query’s existing policy; they are not invented by summing displayed advanced results. A seriesValue and period comparison on the same selection are unavailable together.

A formula selection contains expression, named operand blocks, optional parameters, optional format: {pattern: ...}, and optional advancedCalculation. resultType is accepted as metadata; the executable result type is inferred from completed inputs. There is no reference alongside expression, and no period or nested block on the formula itself. Apply those to a referenced sibling selection and combine its result.

The expression grammar supports arithmetic, comparison, Boolean composition and if. Operands may reference sibling measure selections or declared parameters, contain scalar values with optional dataType, or use supported expression operators. A formula cannot aggregate or call a UDF: select a measure that computes it as a selection of its own and read that selection’s key. A query, or a question sent through MCP, can define that measure in local.measures (see Unsaved definitions and validation); a stored question selects a measure from the layer. Operand names are arbitrary and case-sensitive; braces and line breaks are not name characters. Metadata property names are reserved. Every declared operand must be used; repeated references to the same operand are allowed.

A sibling reference consumes the completed selection, including its parameter overrides and supported calculations. Forward references are allowed. Missing references and dependency cycles are rejected. Formulas depending directly or transitively on final seriesValue are unavailable. A formula that reads a selection with its own advancedCalculation, directly or through another formula, is evaluated after that calculation, so an advancedCalculation on the formula itself is rejected. The exception is a seriesValue when every calculation the formula reads is a total or compareToTotal. Put the calculation on a selection the formula reads instead. For a share of the top N, use Top N or a rank result filter with a total on the plain measure. Renaming a selection updates its local references. Removing one also removes dependent formulas; surviving filters that name removed results require repair.

In the semantic layer editor, formulas have their own Formulas section below Measures. A formula can be added once the question selects at least one measure, and adding the first one gives the question’s measure selections keys. Each formula has a display label, a format, and is either a Calculation (arithmetic over the question’s other measures) or a Condition (an if with then and else branches). A branch can itself be a calculation, such as if({customers} > 0, {tickets} / {customers}, 0). The editor does not offer advanced calculations on a formula; ones set through YAML or MCP are kept when the formula is edited.

orderBy is prioritized final sorting. Each entry contains a dimension or measure reference and optional direction (ascending by default). It is independent of explicit running-calculation ordering. Duplicate targets are invalid. A raw field that needs sorting must first have a named selection; final sorting does not accept a direct {view, field} reference.

defaults property Meaning
topN Integer 1–1000 bounding the complete answer. With several dimensions and a measure, it keeps N values of the ranked dimension, not N rows; by default that is N per combination of the other dimensions.
ranking A selected measure reference and optional direction, independent of final sorting. Requires Top N.
allMode Optional independent. With several dimensions and no rankedDimension, Top N ranks each one alone.
hideZeroValues Optional Boolean suppression of zero measure rows. No effect on dimension-only lists.
showOthers Optional Boolean gathering values outside Top N. Requires measures and Top N.
othersPosition default, first or last.
othersLabel Optional text for the Others row.

Omitting output returns dimensions followed by measures. An explicit list must be nonempty and reference existing selections. Named targets cannot repeat. For physical dimensions in reference arrays, {reference: {view, field}} selects an existing occurrence; repeated identical selected fields are consumed in order. Projection never adds a field, regroups rows or removes calculation dependencies. Questions with explicit output open as a table in Data Explorer.

preferredCharts is an advisory ordered list, not a saved visualization definition. Accepted type values are line, bar, stacked_bar, area, pie, donut, scatter, table, heatmap, funnel, kpi, combo and waterfall. Each entry may include reason. Check rendering support and data compatibility before choosing a chart. A hint does not make a renderer available.

For execution or prepared saving, the same question may include transient local.dimensions and local.measures. These use reusable semantic entity definitions, not selection definitions. Saving promotes eligible locals atomically and stores references; local is not a saved question property. Published mapping and drill-through definitions are required for execution.

Paging (limit, offset), queryTimeout, dryRun, response budgets and runtime parameters belong to the execution request, outside the saved definition. Saving does not publish. Newly created referenced entities must be published before running against the published layer.

Shape checks reject unknown or mixed properties. Semantic validation reports reference, datatype, ordering, dependency and capability errors with entity/property paths. Repairable semantic defects can remain visible in draft documents; typed authoring, publication and execution reject invalid calculations. A schema-valid definition is not evidence of a successful warehouse query.

V3 reads V2 documents and returns canonical V3. New documents, saves and exports write fileVersion: 3. The file version is independent of the MCP tool contract version. Older clients are not guaranteed to understand V3.

Migration converts the old single-operation advancedCalculation: {type: runningTotal, ...} to advancedCalculation: {runningTotal: {...}}, retaining settings and complete lists. Older sorting spellings normalize to orderBy and reference-based ranking. Mixed old/new spellings are rejected.

V2 named-question result filters referenced reusable measures. Migration maps each to its corresponding completed selection. Equivalent repeated selections are resolved deterministically; differently calculated duplicates require repair because the reader cannot infer which result was intended. A filter-only reusable measure becomes a hidden selection, with the original visible output and grain preserved. Existing associative branches and their custom names survive. Reference-array result filters retain their reusable-measure scope.

Older revisions stay readable, and reading one does not rewrite it. This is read compatibility with V2, not a second V2 write format. V1 and unversioned documents are not accepted by this reader; use the supported legacy import workflow where applicable.

The supported surface includes named and array selections, period axes and comparisons, basic period-axis nested reduction, ordinary/associative/result filters, supported advanced composition, sibling result formulas, ranking, output projection and advisory chart hints.

The following are unavailable and cannot be enabled by adding YAML properties:

  • Percent rank, standard score, annualized row growth and approximate group percentiles.
  • Private moving/inter-record ordering and partitions, and formulas after final series selection.
  • Nested percentile, nestedRatio, dimension-value output, retained hidden-series output, correlation, accumulated growth, nested UDF and non-time-period calculation variants.
  • Persisted pivot/chart-family output bindings and Business Question conditional coloring.

Conditional coloring is not part of this contract. Feature availability and datasource support remain separate from document versioning. Use live MCP discovery and the editor’s availability explanations for your environment.