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)。

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

关系的验证规则

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

  • Many-to-one relationships and one-to-one relationships: Relationships work like foreign key constraints.

    Suppose that the logical table table_1 identifies col_1 as a primary key:

    TABLES (
      table_1 AS my_table_1 PRIMARY KEY (col_1)
      ...
    
    Copy

    When you define a relationship as table_2 (col_2) REFERENCES table_1 (col_1), col_1 must be a primary key, and col_2 must serve as a foreign key:

    • If multiple rows in table_2 use the same value in col_2, you're creating a many-to-one relationship from table_2 to table_1.

      For example, orders (o_custkey) REFERENCES customers (c_custkey) creates a many-to-one relationship from orders to customers (many orders can belong to one customer with the key c_custkey).

    • If each row in table_2 has a unique value in col_2, you're creating a one-to-one relationship from table_2 to table_1.

      For example, customer_details_extended (e_custkey) REFERENCES customer_details (c_custkey) creates a one-to-one relationship from customer_details_extended to customer_details (one row of extended details for a customer belongs to one row of customer details with the key c_custkey).

  • Validations performed on one-to-one relationships:

    • Row-level expressions can refer to other row-level expressions at the same (or lower) granularity.

      For example, customer_details and customer_details_extended have a one-to-one relationship, where one row in customer_details is related to one row in customer_details_extended. A row-level expression on each of these tables refers to one specific customer. Each can refer directly to the other in row-level expressions because the row-level expressions are at the same granularity.

      As a corollary, a row-level expression on customer_details cannot reference a metric or aggregation of a row-level expression on customer_details_extended (and vice versa).

    • Aggregate-level expressions must refer to row-level expressions at the same granularity using a single aggregate.

      For example, aggregate-level expressions on customer_details or customer_details_extended must use a single aggregate when referencing the other entity. In addition, metrics on customer_details and customer_details_extended should refer to other metrics on the two entities directly, without any aggregation.

    These rules apply whether the relationship between the entities is defined as customer_details REFERENCES customer_details_extended or customer_details_extended REFERENCES customer_details.

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

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

    Note that one-to-one relationships respect transitivity when interacting with other one-to-one and many-to-one relationships:

    • If logical tables customers and customer_details have a one-to-one relationship and logical tables customer_details and customer_details_extended have a one-to-one relationship, logical tables customers and customer_details_extended are automatically inferred to have a one-to-one relationship and are treated as such during validation.

    • If logical tables customers and customer_details have a one-to-one relationship and logical tables customer_details and regions have a many-to-one relationship, customers is inferred to be transitively many-to-one to regions, which gives customers a higher granularity than regions during expression validation.

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

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

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

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

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

    备注

    If there are multiple paths that can be used to join two tables, you should define separate logical tables and relationships for each path. For information, see Defining different logical tables for different paths that join two tables.

表达式验证规则

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

关于表达式的一般规则

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

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

    例如,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 而不需要额外聚合。但是,在以更高粒度引用指标时,需要进行聚合。

窗口函数指标的规则

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

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

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

语言: 中文