Snowflake 如何验证语义视图

当您定义语义视图时,Snowflake 会验证其是否符合一组验证规则。这些规则可确保您的语义模型格式正确且能够正常运行。

这些规则将在后续章节中解释:

一般验证规则

以下规则一般适用于语义视图:

  • 必填元素: 语义视图必须定义至少一个维度或指标。

    例如,您的 TPC-H 语义视图需要至少一个维度(如 customer_name)或一个指标(如 order_average_value)。

  • 主键和外键: 在主键和外键定义中,必须使用物理基表中的列,或者使用直接引用基表列的逻辑表中定义的表达式(例如,t1.fact AS t1.col)。

    例如,在 TPC-H 架构中,可以用 c_custkey 作为 customer 表的主键,使用 o_custkey 作为``orders`` 表中的外键。c_custkey 和``o_custkey`` 是物理基表中的列。

  • 表别名引用: 在关系或表达式中引用表时,必须使用其定义的别名。

    例如,如果您定义表别名 orders AS snowflake_sample_data.tpch.orders_table,则必须在指标定义中使用表别名 orders``(而不是 ``orders_table)。

    如果不为逻辑表指定别名,则必须在任何表达式中使用逻辑表名称。

关系的验证规则

以下规则适用于语义视图中的关系:

  • 多对一关系: 关系的工作原理与外键约束类似。

    例如,当您将关系定义为 orders (o_custkey) REFERENCES customers (c_custkey) 时,您将会创建从 orderscustomers``(多个订单可以属于一个客户)的多对一关系,其中 ``c_custkey 必须是主键。

  • 传递关系: Snowflake 自动推导间接关系。

    例如,如果您定义 line_items``和``orders 之间的关系以及 orderscustomer 之间的另一种关系,Snowflake 就会知道 line_itemscustomer 之间也存在关系。

  • 没有循环关系: 您无法定义循环关系,即使通过传递路径也是如此。

    例如,您无法定义从 orderscustomer 的关系以及从 customerorders 的另一个关系。

  • 没有自我引用: 目前,表无法引用自身(例如员工经理层次结构,员工可以引用其他员工作为经理)。

  • 多路径关系限制: 您可以在两个表之间定义多个关系,但存在一些限制。

    例如,如果 line_items 通过 order_key 及另一列与 orders 相关,则这些表不能引用彼此的语义表达式。

  • 一对一的关系限制: 一对一的关系存在局限性。

    例如,假设您定义了一个关系 orders(id) REFERENCES order_summary,其中 id 是主键或在 orders 中具有唯一值。order_summary 无法在 orders 语义表达式中引用语义表达式,但 orders 可以引用 order_summary 中的语义表达式。

表达式验证规则

以下规则适用于事实、维度和指标中的语义表达式:

关于表达式的一般规则

以下规则一般适用于语义表达式:

  • 表达式类型: 维度和数值是行级表达式(未聚合),而指标是聚合级别的表达式。

    例如,customer_name 是一个维度(行级),而 order_average_value 是一个指标(聚合级别)。

  • 表关联: 每个语义表达式都必须与表关联。

    例如,customer_name 必须定义为 customer.customer_nameorder_average_value 必须定义为 orders.order_average_value

  • 同表引用: 表达式可以使用限定或非限定名称引用基表列或同一逻辑表上的其他表达式。

    例如,在 orders 表中,您可以将 orders.shipping_month 定义为

    • :code:`MONTH(o_shipdate)`(使用非限定列名称)

    • :code:`MONTH(orders.o_shipdate)`(使用限定名称)

  • 跨表限制: 表达式不能引用其他表中的基表列或无关逻辑表中的表达式。

    例如,除非表中的表达式之间存在关系,否则 customer.customer_name 无法直接引用 orders 表中的表达式。要跨表处理数据,您必须:

    1. 定义逻辑表之间的关系(例如,通过 c_custkey 定义 customerorders 之间的关系)。

    2. 在源表上定义一个数值(例如,orders.total_value)。

    3. 从连接的逻辑表中引用这些表达式(例如,customer.order_value 可以引用 orders.total_value)。

  • 名称解析: 如果语义表达式和列的名称相同,则对该名称的引用解析为语义表达式。

    例如,如果您定义了一个 region 维度并且还有一个 region 列,则表达式中的 region 解析为该维度,而不是列。一个例外情况是表达式在其定义中引用相同的名称(例如,customer.c_name AS customers.c_name)。引用解析为列,而不是定义表达式本身。

  • 表达式引用循环: 无法在表达式之间创建循环引用。

    例如,您不能先定义基于 orders.customer_valuecustomer.total_value,然后定义基于 customer.total_valueorders.customer_value

  • 表引用循环: 您不能在表达式定义中的逻辑表之间创建循环引用。

    例如,您不能先定义基于 orders.customer_valuecustomer.total_value,然后定义基于 customer.c_custkey.orders.customer_count

  • 函数用法: 可以像 YEAR* / DAY* / WEEK* / MONTH / QUARTER 一样在维度中一样使用标量函数,但不允许使用表函数。

行级表达式的规则(维度和事实)

以下规则适用于维度和事实中的行级表达式:

  • 同表引用: 行级表达式可以直接引用其自身表中的列。

    例如,customers.customer_name 可以直接定义为 customers.c_name

  • 相等或更低的粒度: 行级表达式可以直接引用相同或更低粒度的其他行级表达式。

    例如,orders.order_details 可以引用 customer.customer_name,因为 customer 粒度低于 ``orders``(一个客户可以有多个订单)。

  • 更高粒度的引用: 在以更高的粒度引用行级表达式时,行级表达式必须使用聚合。

    例如,customer.total_orders 必须使用 COUNT(orders.o_orderkey),因为``orders`` 的粒度高于 ``customer``(一个客户可以有多个订单)。

  • 汇总参考: 诸如 orders.order_type 的维度不能引用诸如 orders.order_average_value 的指标,但 customer.customer_segment 可以应用 orders.order_average_value,因为 customer 的粒度低于订单。

聚合级表达式的规则(指标)

以下规则适用于指标中的聚合级别表达式:

  • 基本聚合: 指标必须使用聚合函数。

    例如,orders.order_average_value 必须使用 AVG(orders.o_totalprice)

  • 等于或更低的粒度: 在以相等或更低粒度引用行级表达式时,指标必须使用单个聚合。

    例如,orders.total_value 可以使用 SUM(line_items.discounted_price),因为 line_items 的粒度低于订单。

  • 更高的粒度引用: 在以更高粒度引用行级表达式时,指标必须使用嵌套聚合。

    例如,customer.average_order_value 必须使用 AVG(SUM(orders.o_totalprice)),因为 orders 的粒度高于 customer

  • 其他聚合引用: 指标可以直接引用相同或更低粒度的其他指标,而不需要聚合。

    例如,orders.profit_margin 可以定义为 orders.total_revenue / orders.total_cost 而不需要额外聚合。但是,在以更高粒度引用指标时,需要进行聚合。

窗口函数指标的规则

这些规则适用于 窗口函数指标

  • 行级计算(数值和维度)不能使用窗口函数指标。

  • 窗口函数指标不能用于其他指标的定义。

语言: 中文