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)
时,您将会创建从orders
到customers``(多个订单可以属于一个客户)的多对一关系,其中 ``c_custkey
必须是主键。传递关系: Snowflake 自动推导间接关系。
例如,如果您定义
line_items``和``orders
之间的关系以及orders
和customer
之间的另一种关系,Snowflake 就会知道line_items
和customer
之间也存在关系。没有循环关系: 您无法定义循环关系,即使通过传递路径也是如此。
例如,您无法定义从
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.
一对一的关系限制: 一对一的关系存在局限性。
例如,假设您定义了一个关系
orders(id) REFERENCES order_summary
,其中id
是主键或在orders
中具有唯一值。order_summary
无法在orders
语义表达式中引用语义表达式,但orders
可以引用order_summary
中的语义表达式。
表达式验证规则¶
以下规则适用于事实、维度和指标中的语义表达式:
关于表达式的一般规则¶
以下规则一般适用于语义表达式:
表达式类型: 维度和数值是行级表达式(未聚合),而指标是聚合级别的表达式。
例如,
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
而不需要额外聚合。但是,在以更高粒度引用指标时,需要进行聚合。
窗口函数指标的规则¶
这些规则适用于 窗口函数指标:
行级计算(数值和维度)不能使用窗口函数指标。
窗口函数指标不能用于其他指标的定义。