Cubos e medidas
O elemento Cube
Um cubo (<Cube>) é uma coleção nomeada de dimensões e medidas.
Dimensões vivem dentro de um elemento contêiner <Dimensions>. Por convenção, elas são declaradas primeiro, seguidas das medidas organizadas em measure groups sob um elemento contêiner <MeasureGroups>. Um measure group é uma coleção de medidas que compartilham a mesma tabela de fato. Cubos simples têm exatamente um measure group; cubos mais avançados podem ter vários — por exemplo, quando você quer combinar uma tabela de fato transacional com uma tabela de rollup pré-agregada.
Atributos de Cube
| Atributo | Obrigatório | Default | Descrição |
|---|---|---|---|
name | sim | — | Nome de exibição usado em consultas MDX |
defaultMeasure | não | — | Medida selecionada quando nenhuma é especificada na consulta |
caption | não | — | Sobrescreve o nome de exibição para ferramentas cliente |
description | não | — | Descrição legível |
visible | não | true | Se o cubo aparece para ferramentas cliente |
cache | não | true | Se o Mondrian cacheia agregados para este cubo |
enabled | não | true | Desabilitar um cubo o esconde sem removê-lo |
enableScenarios | não | false | Habilita cenários de write-back / what-if |
Como tabelas de fato e dimensões se conectam
O cubo [Sales] no exemplo de estrutura do schema tem seu measure group baseado na tabela "sales_fact_1997". Cada tabela referenciada no schema lógico também deve aparecer no bloco <PhysicalSchema>.
A tabela de fato contém as colunas das quais as medidas são calculadas, mais colunas de foreign key que ligam às tabelas de dimensão. O Mondrian precisa saber de todas:
- Cada coluna de medida aparece dentro de uma definição
<Measure>. - Cada coluna de foreign key aparece dentro de um elemento
<ForeignKeyLink>, conectando o measure group à dimensão apropriada.
measure_groups:- name: "Sales" table: "sales_fact_1997" measures: - name: "Unit Sales" column: "unit_sales" aggregator: "sum" format_string: "#,###" - name: "Store Sales" column: "store_sales" aggregator: "sum" format_string: "#,###.##" - name: "Store Cost" column: "store_cost" aggregator: "sum" format_string: "#,###.00" dimension_links: - type: "foreign_key" dimension: "Customer" foreign_key_column: "customer_id" - type: "foreign_key" dimension: "Time" foreign_key_column: "time_id"<MeasureGroup name="Sales" table="sales_fact_1997"> <Measures> <Measure name="Unit Sales" column="unit_sales" aggregator="sum" formatString="#,###"/> <Measure name="Store Sales" column="store_sales" aggregator="sum" formatString="#,###.##"/> <Measure name="Store Cost" column="store_cost" aggregator="sum" formatString="#,###.00"/> </Measures> <DimensionLinks> <ForeignKeyLink dimension="Customer" foreignKeyColumn="customer_id"/> <ForeignKeyLink dimension="Time" foreignKeyColumn="time_id"/> </DimensionLinks></MeasureGroup>Medidas
Atributos de Measure
Cada elemento <Measure> tem os seguintes atributos:
| Atributo | Obrigatório | Default | Descrição |
|---|---|---|---|
name | sim | — | Nome de exibição usado em consultas MDX |
column | sim* | — | Coluna na tabela de fato. Use um nome de coluna calculada se o valor for derivado |
aggregator | sim | — | Função de agregação — veja abaixo |
formatString | não | — | Como o valor é formatado para exibição |
datatype | não | Numeric | Como os valores são armazenados no cache do Mondrian e retornados via XML for Analysis |
caption | não | — | Sobrescreve o nome de exibição para ferramentas cliente |
description | não | — | Descrição legível |
visible | não | true | Se a medida aparece para ferramentas cliente |
formatter | não | — | Nome qualificado da classe de um cell formatter customizado |
table | não | — | Sobrescreve a tabela do measure group para esta medida (avançado) |
* column é obrigatório a menos que você aponte para uma coluna calculada definida no schema físico.
Tipos de agregador
O atributo aggregator suporta os seguintes valores:
| Valor | Significado |
|---|---|
sum | Soma de todos os valores |
count | Contagem de linhas |
min | Valor mínimo |
max | Valor máximo |
avg | Média aritmética |
distinct-count | Contagem de valores distintos |
median | Mediana (50º percentil) — não-aditivo |
percentile | Um percentil (defina percentile="0..100", default 50) — não-aditivo |
distinct-count tem limitações quando o cubo contém uma hierarquia parent-child.
Agregadores não-aditivos: median e percentile
median e percentile são agregadores folha não-aditivos: não existe mediana das medianas, então não podem ser combinados a partir de sub-agregados. O Saiku os empurra para SQL como PERCENTILE_CONT(fraction) WITHIN GROUP (ORDER BY column) e os computa no grão exato que você consultou — eles são deliberadamente excluídos da substituição por tabela agregada e do rollup de segmento por cache (para que você nunca obtenha uma “mediana de medianas” errada).
measures:- name: "Median Order Value" column: "order_total" aggregator: "median"- name: "P90 Latency" column: "latency_ms" aggregator: "percentile" percentile: "90"<Measure name="Median Order Value" column="order_total" aggregator="median"/><Measure name="P90 Latency" column="latency_ms" aggregator="percentile" percentile="90"/>Eles exigem o backend Calcite (o default do Saiku) em um banco que suporte PERCENTILE_CONT — PostgreSQL, Oracle, SQL Server, Snowflake, BigQuery, H2, DuckDB e similares. Em um backend sem ele, a consulta é recusada com um erro claro em vez de retornar um número errado. A troca é intencional: você perde pré-agregação/rollup de cache para essas medidas, em troca de um valor correto no grão consultado.
Tipos de dados
O atributo datatype controla como os valores de célula são armazenados no cache do Mondrian e retornados por XML for Analysis. Valores aceitos são String, Integer, Numeric, Boolean, Date, Time e Timestamp. O default é Numeric, exceto para medidas count e distinct-count, que default para Integer.
Format strings
O atributo opcional formatString controla como um valor é impresso. Os símbolos , e . são sensíveis à locale — se você está rodando em italiano, #,###.00 pode produzir 48.123,45. Alguns padrões comuns:
| Padrão | Exemplo de saída |
|---|---|
#,### | 32,910 |
#,###.## | 69,798.23 |
#,###.00 | 69,798.23 |
$#,##0.00 | $69,798.23 |
Standard | default de locale |
Para padrões avançados de data e formatos condicionais, veja a referência de format strings do MDX.
Caption
Uma medida pode ter um atributo caption que é retornado em vez do name pelas APIs cliente. Isso é útil quando você quer localizar o nome de uma medida ou exibir caracteres especiais:
measures:- name: "Sum X" column: "sum_x" aggregator: "sum" caption: "Σ X"<Measure name="Sum X" column="sum_x" aggregator="sum" caption="Σ X"/>Colunas calculadas em medidas
Em vez de apontar uma medida para uma coluna bruta, você pode derivar o valor de uma expressão SQL. Defina uma coluna calculada na declaração <PhysicalSchema> da tabela de fato e referencie-a por nome na <Measure>:
calculated_columns:- name: "promotion_sales" expression: generic: "(case when {col:promotion_id} = 0 then 0 else {col:store_sales}\ \ end)"<Table name="sales_fact_1997"> <ColumnDefs> <CalculatedColumnDef name="promotion_sales"> <ExpressionView> <SQL dialect="generic">(case when <Column name="promotion_id"/> = 0 then 0 else <Column name="store_sales"/> end)</SQL> </ExpressionView> </CalculatedColumnDef> </ColumnDefs></Table>Depois referencie essa coluna como qualquer outra:
measures:- name: "Promotion Sales" column: "promotion_sales" aggregator: "sum" format_string: "#,###.00"<Measure name="Promotion Sales" aggregator="sum" column="promotion_sales" formatString="#,###.00"/>O <PhysicalSchema> reúne todos os detalhes de implementação em um lugar. A definição <Measure> não precisa saber — nem se importar — que promotion_sales é calculada. Toda vez que o Mondrian precisa acessá-la, o engine substitui pela expressão SQL. Expressões SQL arbitrárias são suportadas, incluindo subqueries, contanto que o banco subjacente possa avaliá-las em contexto de agregado.
Chaves compostas e dimension links
Quando a chave de uma dimensão abrange mais de uma coluna, você expressa isso com um bloco <Key> multi-coluna no <Attribute>:
attributes:- name: "Quarter" key: - "the_year" - "quarter"<Attribute name="Quarter"> <Key> <Column name="the_year"/> <Column name="quarter"/> </Key></Attribute>Se há apenas uma coluna de chave, <Key> e o atributo shorthand keyColumn são equivalentes — use o que for mais claro. Você não precisa especificar nameColumn separadamente quando default para a última coluna da chave composta.
Quando uma tabela de dimensão tem uma primary key composta, o <ForeignKeyLink> no <MeasureGroup> da tabela de fato deve fornecer uma coluna de foreign key por coluna na chave composta. Veja Schema físico para a referência completa de links.