Cuándo usar kpi
KPI es la elección correcta cuando la respuesta es un solo número — total de revenue, count de orders, tasa de conversión, error budget consumido. Agrega un delta o un valor secundario para mostrar dirección o comparación al lado del headline. KPI es el "headline" típico de un dashboard: no emite clicks (no hay dimension para clickear), pero reacciona a filtros de dashboard y pills de cross-filter como cualquier otra viz — su query subyacente re-corre con los params activos y el número headline se recomputa.
Si necesitas un número por categoría en vez de un solo número, usa bar. Si necesitas un trend en el tiempo, usa line. Si necesitas muchos números en un layout tabular, usa grid.
El identifier de tipo es kpi — no existe un tipo number; la validación lo rechaza.
Mapping
El KPI lee la primera fila del resultado de la query. Los campos de mapping nombran qué columnas de esa fila se vuelven qué elemento visual:
mapping.value— requerido. El field cuyo valor es el número headline.mapping.subtitle— field string para una línea de contexto label / período debajo del valor.mapping.delta— field numérico mostrado como indicador de cambio. El signo maneja la flecha up/down; la config de polaridad controla el color.mapping.secondary_value— field numérico para un valor de comparación (ej. "período anterior") cuando no haydelta. Mapea uno u otro: cuando están los dos, el renderer muestra el delta.mapping.secondary_label— caption parasecondary_value, escrito como string literal (ej."Invoices","Previous quarter"). También acepta un nombre de campo: si el valor coincide con una columna de la fila de resultado, se usa el valor de esa columna como caption. Default a"Previous"cuando se omite.mapping.secondary_plain— field de texto plano mostrado al lado del headline cuando no hay delta ni valor secundario.mapping.comparison— field numérico que maneja el bloquecomparisonde abajo (lecturas período contra período).
mapping:
value: revenue
subtitle: period_label
delta: revenue_delta_pct
La regla de una fila significa que el lado Malloy de un KPI es una view solo de aggregate:. Producir la columna delta es parte de la query, no de la viz — un shape que funciona compara la ventana con la ventana anterior de igual longitud:
# models/ec_performance.malloy (excerpt)
##! experimental.parameters
source: ec_performance() is ecommerce.sql("""
WITH windows AS (
SELECT
SUM(IF(created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY),
sale_price, 0)) AS revenue,
SUM(IF(created_at < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
AND created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 60 DAY),
sale_price, 0)) AS revenue_prev
FROM `bigquery-public-data.thelook_ecommerce.order_items`
)
SELECT
revenue,
'Last 30 days' AS period_label,
SAFE_DIVIDE(revenue - revenue_prev, revenue_prev) AS revenue_delta_pct
FROM windows
""") extend {
view: kpi is { select: * }
}
Bloque kpi
Las opciones específicas de KPI viven bajo el bloque top-level kpi. KPI no tiene un bloque chart.
kpi.comparison_label— caption mostrado debajo del delta (ej."vs. last week"). Cuando se omite, el renderer compone un default tipo "Up vs previous period" desde el signo del delta.kpi.delta_good_when—"increase"(default) o"decrease". Setea la polaridad que colorea el delta en verde vs rojo. Usa"decrease"para métricas donde menos es mejor — refunds, error rate, time-to-resolution.
Bloque comparison
El bloque top-level comparison renderiza una lectura período contra período desde el field nombrado en mapping.comparison:
comparison.enabled— boolean.comparison.direction—"auto"deriva la flecha up/down del signo del valor.comparison.period_label— caption para la comparación (ej."vs budget to date").
mapping:
value: attainment_pct
comparison: attainment_pct
format:
value: "#,##0.00%"
comparison: "#,##0.00%"
comparison:
enabled: true
direction: auto
period_label: "vs budget to date"
Nota que las entries de format de arriba son slot-keyed (value, comparison) en vez de field-keyed — las dos formas funcionan, y las keys de slot se leen mejor cuando el mismo field llena dos slots.
format
El format de número es field-keyed. Patterns por field ganan sobre el pattern root.
format.value— pattern para el número headline.format.delta— pattern para el indicador delta.format.secondary_value— pattern para el valor de comparación secundario.formaten root — fallback cuando falta una entry field-específica.
# headline as abbreviated currency, delta as percent
format:
revenue: "$#,##0a"
revenue_delta_pct: "#,##0.00%"
La gramática de patterns completa vive en el overview de viz-types.
Comportamiento de cross-filter
KPI participa en cross-filtering solo como consumer:
- No emite. Clickear un KPI no agrega un pill — no hay dimension para clickear.
- Sí reacciona. Los pills seteados en otra parte del dashboard, y cualquier filtro a nivel dashboard, se vuelven parámetros en el próximo run, y la query subyacente del KPI re-corre con ellos. El número headline se recomputa en consecuencia.
Si quieres un "headline que siempre muestre el total dashboard-wide" sin importar los pills, escribe la query Malloy subyacente para que los defaults de su parámetro ignoren los valores de pill (ej. aceptar el parámetro pero no usarlo en el where-clause), o usa dos items KPI separados: uno atado a un model que ignora el parámetro de cross-filter, otro atado a un model que lo respeta.
Ejemplos trabajados
Headline con delta y polaridad de porcentaje favoreciendo decrease (menor error rate es mejor):
id: ec_error_rate_kpi
title: Error Rate
query: "models/ec_quality.malloy::error_rate_kpi"
type: kpi
mapping:
value: error_rate
delta: error_rate_delta_pct
subtitle: period_label
format:
error_rate: "#,##0.00%"
error_rate_delta_pct: "#,##0.00%"
kpi:
comparison_label: "vs previous period"
delta_good_when: decrease
published: true
Headline con un valor de comparación secundario (sin delta):
id: ec_revenue_vs_prev_kpi
title: Revenue
query: "models/ec_revenue.malloy::current_vs_previous"
type: kpi
mapping:
value: revenue_current
secondary_value: revenue_previous
secondary_label: "Previous quarter"
format:
revenue_current: "$#,##0a"
revenue_previous: "$#,##0a"
published: true
Headline con una anotación de texto plano cuando la métrica no tiene una comparación numérica:
id: ec_top_brand_kpi
title: Top Brand
query: "models/ec_revenue.malloy::top_brand"
type: kpi
mapping:
value: brand_name
secondary_plain: market_share_label
published: true