Business question YAML reference
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.
Complete document example
Section titled “Complete document example”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: 3name: Sales analysisviews: 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: monthmeasures: 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: ascendingAn 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.
Question properties
Section titled “Question properties”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.
Selection keys and reference scope
Section titled “Selection keys and reference scope”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.
Filters and parameters
Section titled “Filters and parameters”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.
Associative membership
Section titled “Associative membership”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 }Execution overrides
Section titled “Execution overrides”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.
Period bindings and nested reduction
Section titled “Period bindings and nested reduction”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:
dimensionsnames one or more stored dimensions. The measure is computed per combination of them, thenaggregatereduces 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 anadvancedCalculationruns over the reduced values. - A reduction along time:
dimensionsholds exactly one period-axis reference, with an optional innerperiodAxisbinding. 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 }]Advanced calculation blocks
Section titled “Advanced calculation blocks”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; omitapproximatefor 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.
Result formulas
Section titled “Result formulas”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.
Sorting, ranking and output
Section titled “Sorting, ranking and output”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.
Unsaved definitions and validation
Section titled “Unsaved definitions and validation”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.
Migration and compatibility
Section titled “Migration and compatibility”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.
Availability
Section titled “Availability”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.