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_1identifiescol_1as a primary key:TABLES ( table_1 AS my_table_1 PRIMARY KEY (col_1) ...
When you define a relationship as
table_2 (col_2) REFERENCES table_1 (col_1),col_1must be a primary key, andcol_2must serve as a foreign key:If multiple rows in
table_2use the same value incol_2, you're creating a many-to-one relationship fromtable_2totable_1.For example,
orders (o_custkey) REFERENCES customers (c_custkey)creates a many-to-one relationship fromorderstocustomers(many orders can belong to one customer with the keyc_custkey).If each row in
table_2has a unique value incol_2, you're creating a one-to-one relationship fromtable_2totable_1.For example,
customer_details_extended (e_custkey) REFERENCES customer_details (c_custkey)creates a one-to-one relationship fromcustomer_details_extendedtocustomer_details(one row of extended details for a customer belongs to one row of customer details with the keyc_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_detailsandcustomer_details_extendedhave a one-to-one relationship, where one row incustomer_detailsis related to one row incustomer_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_detailscannot reference a metric or aggregation of a row-level expression oncustomer_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_detailsorcustomer_details_extendedmust use a single aggregate when referencing the other entity. In addition, metrics oncustomer_detailsandcustomer_details_extendedshould 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_extendedorcustomer_details_extended REFERENCES customer_details.传递关系: Snowflake 自动推导间接关系。
例如,如果您定义
line_items``和``orders之间的关系以及orders和customer之间的另一种关系,Snowflake 就会知道line_items和customer之间也存在关系。Note that one-to-one relationships respect transitivity when interacting with other one-to-one and many-to-one relationships:
If logical tables
customersandcustomer_detailshave a one-to-one relationship and logical tablescustomer_detailsandcustomer_details_extendedhave a one-to-one relationship, logical tablescustomersandcustomer_details_extendedare automatically inferred to have a one-to-one relationship and are treated as such during validation.If logical tables
customersandcustomer_detailshave a one-to-one relationship and logical tablescustomer_detailsandregionshave a many-to-one relationship,customersis inferred to be transitively many-to-one toregions, which givescustomersa higher granularity thanregionsduring expression validation.
没有循环关系: 您无法定义循环关系,即使通过传递路径也是如此。
例如,您无法定义从
orders到customer的关系以及从customer到orders的另一个关系。没有自我引用: 目前,表无法引用自身(例如员工经理层次结构,员工可以引用其他员工作为经理)。
多路径关系限制: 您可以在两个表之间定义多个关系,但存在一些限制。
例如,如果
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_name,order_average_value必须定义为orders.order_average_value。同表引用: 表达式可以使用限定或非限定名称引用基表列或同一逻辑表上的其他表达式。
例如,在
orders表中,您可以将orders.shipping_month定义为跨表限制: 表达式不能引用其他表中的基表列或无关逻辑表中的表达式。
例如,除非表中的表达式之间存在关系,否则
customer.customer_name无法直接引用orders表中的表达式。要跨表处理数据,您必须:定义逻辑表之间的关系(例如,通过
c_custkey定义customer和orders之间的关系)。在源表上定义一个数值(例如,
orders.total_value)。从连接的逻辑表中引用这些表达式(例如,
customer.order_value可以引用orders.total_value)。
名称解析: 如果语义表达式和列的名称相同,则对该名称的引用解析为语义表达式。
例如,如果您定义了一个
region维度并且还有一个region列,则表达式中的region解析为该维度,而不是列。一个例外情况是表达式在其定义中引用相同的名称(例如,customer.c_name AS customers.c_name)。引用解析为列,而不是定义表达式本身。表达式引用循环: 无法在表达式之间创建循环引用。
例如,您不能先定义基于
orders.customer_value的customer.total_value,然后定义基于customer.total_value的orders.customer_value。表引用循环: 您不能在表达式定义中的逻辑表之间创建循环引用。
例如,您不能先定义基于
orders.customer_value的customer.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而不需要额外聚合。但是,在以更高粒度引用指标时,需要进行聚合。
窗口函数指标的规则¶
这些规则适用于 窗口函数指标:
行级计算(数值和维度)不能使用窗口函数指标。
窗口函数指标不能用于其他指标的定义。