Skip to content

指标定义

在语义层中定义计算和关键绩效指标(KPIs)

指标介绍

指标是基于语义模型中度量或维度的计算。它们代表关键业务绩效指标(KPIs)和其他常用计算,集中封装业务逻辑。

基本结构定义如下:

yaml
metrics:
  - name: metric_name     # 必需 - 指标的唯一标识符
    expr: "SQL_expression" # 必需 - 定义计算的SQL表达式
    description: "业务定义" # 必需 - 指标的清晰解释
    args:                   # 可选 - 用于参数化指标
      - name: parameter_name
        type: parameter_type
        description: "参数描述"
        default: default_value        # 可选

指标 vs 度量

区分指标(metrics)与度量(measures)和维度(dimensions)很有帮助:

  • 维度:用于分组或筛选的描述性属性(如国家、状态)
  • 度量:表示对单列的直接可聚合计算,通常对应于原始数据字段(如SUM(amount)定义为名为total_amount的度量)
  • 指标:定义更复杂的计算、业务逻辑或关键绩效指标(KPIs),通常组合多个度量、维度或涉及条件逻辑

指导原则

  • 如果需要简单的直接列聚合(如求和、计数、平均),定义为度量
  • 如果需要定义特定的业务KPI、比率、涉及多个步骤或度量的计算,或参数化计算,定义为指标

定义基础指标

核心指标包含名称、计算表达式(expr)和描述。

字段是否必需描述
name模型中指标的唯一名称
expr定义指标计算的SQL表达式,可引用度量、维度和参数
description指标的人类可读描述
args参数化指标表达式的参数对象列表

编写表达式

expr字段使用与数据仓库兼容的SQL语法定义指标计算。

  • 引用字段:可直接引用同一模型中定义的维度和度量
  • 聚合函数:使用标准SQL聚合函数(SUM, AVG, COUNT等)
  • 运算符:支持算术、逻辑和比较运算符
  • 函数:可使用大多数标准SQL函数

示例:基础指标

yaml
metrics:
  - name: total_revenue
    expr: "SUM(orders.amount)"
    description: >
      通过汇总查询上下文中所有订单的'amount'计算总收入。代表毛收入。

  - name: order_count
    expr: "COUNT(DISTINCT orders.order_id)"
    description: >
      基于'order_id'的不同计数,查询上下文中包含的唯一订单总数。

高级指标类型

除了基础计算,还可以创建更动态和互连的指标。

参数化指标

创建接受用户查询时输入的灵活指标。使用双花括号引用参数。

示例:参数化指标

yaml
metrics:
  - name: revenue_in_last_n_days
    description: 计算用户指定或默认为30天的最近N天的总收入。
    expr: "SUM(CASE WHEN orders.order_date >= DATE_SUB(CURRENT_DATE(), INTERVAL {{days}} DAY) THEN orders.amount ELSE 0 END)"
    args:
      - name: days
        type: number
        description: 收入计算中包含的天数。
        default: 30

跨模型指标

使用点符号(related_model_name.field_name)引用相关模型中的字段。这需要在相关模型之间定义关系。

示例:跨模型指标

yaml
metrics:
  - name: revenue_per_customer
    description: >
      订单查询上下文中每个唯一客户的平均收入。需要通过'customer'关系将'orders'模型与'customers'模型连接。
    expr: "SUM(orders.amount) / NULLIF(COUNT(DISTINCT customer.id), 0)"

复合指标

yml
  - name: total_ship_amount # 基础指标
  label: 发货总金额
  description: >
    发货金额、发货总金额、出库金额、出库总金额。
  expr: SUM(ship_amount)
  type: double
  format: '¥#,##0.00'

  - name: total_refund_amount # 基础指标
  label: 退货总金额
  description: >
    退货总金额、退货金额、退货额。
  expr: SUM(refund_amount)
  type: double
  format: '¥#,##0.00'

- name: total_income_amount # 复合指标
  label: 收入
  description: >
    退后GMV、收入、总收入、收入金额、收入总金额、销售额。
  expr: "{{ metric('total_ship_amount') }} - {{ metric('total_refund_amount') }}"
  type: double
  format: '¥#,##0.00'

最佳实践与注意事项

遵循这些指南创建健壮、可理解和可维护的指标。

通用最佳实践

  • 业务导向:定义代表有意义业务KPI的指标
  • 清晰命名与描述:使用一致、描述性名称并提供清晰描述
  • 利用现有组件:通过引用模型中现有度量和维度构建指标
  • 记录依赖关系:明确说明指标对参数或相关模型数据的依赖

表达式最佳实践

  • 类型一致性:确保表达式解析为适合聚合的适当数据类型
  • 使用表前缀:引用相关模型字段时始终使用表限定名称
  • SQL约定
    • 用括号包裹复杂表达式确保正确运算符优先级
    • 使用NULLIF处理除零错误
    • 注意空值处理
  • 避免循环引用

良好表达式示例(参数化):

yaml
metrics:
  - name: avg_order_value_by_date
    description: 指定日期范围内订单的平均订单价值。
    expr: "SUM(CASE WHEN orders.created_at BETWEEN '{{start_date}}' AND '{{end_date}}' THEN orders.amount ELSE 0 END) / NULLIF(COUNT(CASE WHEN orders.created_at BETWEEN '{{start_date}}' AND '{{end_date}}' THEN orders.id ELSE NULL END), 0)"
    args:
      - name: start_date
        type: date
        description: 开始日期(YYYY-MM-DD)。
      - name: end_date
        type: date
        description: 结束日期(YYYY-MM-DD)。

参数最佳实践

  • 显式类型:始终为每个参数定义类型
  • 参数字段:确保args列表中的每个参数包含必需字段
  • 默认值:为可选参数提供默认值
  • 清晰文档:为每个参数提供有意义的描述
  • 占位符:使用双花括号引用参数

综合示例

以下是订单模型上下文中的示例,包含各种指标类型和实践:

yaml
name: orders
description: >
  表示单个客户订单交易。包含每个订单的详细信息,
  包括标识符、客户链接、时间、状态和财务价值。
dimensions:
  - name: order_id
    description: 订单交易的唯一标识符。
    type: string
  - name: order_date
    description: 订单下单日期。
    type: date
  - name: status
    description: 订单的当前履行或支付状态。
    type: string
  - name: customer_id
    description: 将订单链接到客户的标识符。
    type: string
measures:
  - name: amount
    description: 订单的总货币价值(如美元)。
    type: number
  - name: item_count
    description: 订单中包含的不同商品数量。
    type: integer
metrics:
  # 基础指标
  - name: total_revenue
    description: 通过汇总查询上下文中所有订单的'amount'计算总收入。
    expr: "SUM(orders.amount)"

  - name: average_order_value
    description: 计算查询结果中所有订单的平均'amount'。
    expr: "AVG(orders.amount)"

  # 参数化指标
  - name: revenue_by_period
    description: 最近N天内下单的订单总收入。
    expr: "SUM(CASE WHEN orders.order_date >= DATE_SUB(CURRENT_DATE(), INTERVAL {{days}} DAY) THEN orders.amount ELSE 0 END)"
    args:
      - name: days
        type: number
        description: 计算中回溯的天数(整数)。
        default: 30

  # 跨模型指标
  - name: revenue_per_customer
    description: 订单查询上下文中每个唯一客户的平均收入。
    expr: "SUM(orders.amount) / NULLIF(COUNT(DISTINCT customer.id), 0)"

  # 更复杂的参数化指标
  - name: revenue_growth_vs_prior_periods
    description: >
      计算与N个周期前相比的总收入百分比增长。
      注意:此计算依赖于`LAG`窗口函数。
    expr: "(SUM(orders.amount) - LAG(SUM(orders.amount), {{periods}}) OVER (ORDER BY orders.order_date)) / NULLIF(LAG(SUM(orders.amount), {{periods}}) OVER (ORDER BY orders.order_date), 0)"
    args:
      - name: periods
        type: number
        description: 比较的先前周期数(如1表示紧接的前一个周期)。
        default: 1