语义视图能力与限制参考
本文集中说明语义视图支持的能力和当前边界,供你在设计视图或排查报错时查阅。每条能力和限制都附最小复现 SQL 和真实输出/报错。
功能概述
语义视图通过声明式定义把多表关系、维度和指标沉淀为业务语义层。指标支持通用聚合函数、算术表达式、条件聚合和窗口函数,DDL 支持
CREATE OR REPLACE 和 SHOW CREATE 回读定义。仍有少数边界(窗口函数的 PARTITION BY 用维度限定名且受同表约束、跨表指标相除等),设计前先了解这些边界可以避免"创建成功但查询出错"这类问题。需要完整查询语法见查询语义视图,跨表关系的聚合粒度见语义视图关系建模与聚合粒度。
指标定义能力
指标体是标准的聚合表达式,支持范围很广:
- 通用聚合函数:不限于
/COUNT
/SUM
/AVG
/MIN
,还包括MAX
、COUNT(DISTINCT ...)
、SUM(DISTINCT ...)
、APPROX_COUNT_DISTINCT
、STDDEV
、VARIANCE
、MEDIAN
、PERCENTILE(col, p)
、GROUP_CONCAT
等。ANY_VALUE - 条件聚合:
,以及标准 SQL 的COUNT(CASE WHEN ...)
过滤指标——每个聚合的过滤条件独立生效,可在同一视图里并列定义分段 KPI 并一起查询。<聚合函数>(...) FILTER (WHERE <条件>) - 算术表达式指标:
、MAX(col) - MIN(col)
、SUM(col) / COUNT(col)
这类在指标体内直接做运算是支持的,单独查询和与其他指标混查都返回正确结果。SUM(col) * 100.0 / SUM(col)
派生指标(同表) —— 支持。同一逻辑表内既可把两个聚合的比值直接写在一个指标体里,也可引用同表已命名的其他指标做运算:
两种写法都支持,且可组合同表任意已命名指标。
窗口函数指标 —— 支持。可在指标体内使用窗口函数(
RANK()/ROW_NUMBER() 等排名,或 SUM(SUM(...)) OVER (...) 这类聚合套窗口做占比、累计),但 PARTITION BY / ORDER BY 有三条约束:
- 必须引用维度的限定别名(如
),不能用物理列名(orders.region
)或裸别名(o_region
),否则报region
或must reference a declared dimension by its alias
。cannot resolve column - partition/order 维度受同表约束:只能是指标所在逻辑表的维度;跨表引用父表维度(如指标在
、orders
)报PARTITION BY customers.region
。cannot resolve column - 查询时该维度必须出现在
的semantic_view()
中,否则报明确语义错。DIMENSIONS
具体示例与实测输出见创建语义视图的"带窗口函数指标的语义视图"。
以下指标定义仍不受支持:
跨表指标相除 —— 一个指标体只能引用自己所在表的列,不能引用其他表的列。例如在
customer 表的指标里写 COUNT(customer.c_custkey) / COUNT(nation.n_nationkey),会因引用不到 nation 的列而报 cannot resolve column 'n_nationkey'。派生指标只能组合同表的聚合(见上文"派生指标")。要聚合更细子表的列,用双层聚合或 FACTS 透传(见下文"跨表指标与粒度")。
NULL 值处理
语义视图的 NULL 处理遵循标准 SQL 语义,几个容易困惑的点:
- NULL 维度值单独成组,不会被丢弃。按含 NULL 的维度分组时,所有 NULL 行聚成一个
分组参与聚合。NULL - 聚合函数跳过 NULL:
/SUM
/AVG
/MIN
/MAX
都忽略 NULL 值。因此COUNT(<列>)
的分母是非 NULL 行数,不是总行数;AVG
只数非 NULL,而COUNT(<列>)
数全部行——同一组里这两个值可能不同。COUNT(<主键>) - 空结果集:对空表或过滤后无行的分组,
返回COUNT
,0
/SUM
等返回AVG
(不报错)。NULL - 除法零除返回 NULL:派生指标里若分母算出
(如0
恰好为 0),该指标返回SUM(x) / (COUNT(a) - COUNT(b))
而不是报错。因此无需为零除额外加保护,但要注意结果中的NULL
可能来自零除而非缺数据。NULL
元数据子句
维度元数据子句在
CREATE 时的书写顺序是固定的:WITH SYNONYMS 必须写在 is_unique/is_time/enum_values 之前,否则报语法错误(Syntax error at or near 'WITH')。
这些子句会持久化,可通过
DESC EXTENDED 回读,但回读保真度不一:
(可多个)、WITH SYNONYMS
—— 回读值与创建值一致。enum_values
、is_unique
—— 只反映"是否声明过",不反映设定的值:只要在is_time
时写了该子句,CREATE
一律回读为DESC EXTENDED
(即便创建时写的是true
);完全不写该子句时,= false
中不出现对应行。因此不能依赖DESC EXTENDED
判断DESC EXTENDED
/is_unique
的真实取值,应以创建脚本为准。is_time
回读的 DDL 只含SHOW CREATE SEMANTIC VIEW
,不含WITH SYNONYMS
/is_unique
/is_time
;需要看这些用enum_values
。DESC EXTENDED
需要过滤时,用
FILTER (WHERE ...) 条件聚合指标(见"指标定义能力"),或在 semantic_view() 外层用 WHERE + 维度短名实现。
关系与查询限制
- 查询必须至少指定一个
、DIMENSIONS
或METRICS
,否则报FACTS
。table or view not found - semantic_view - 不能在同一次查询中组合来自两个无直接关系路径的分支的指标(chasm trap),会报
。No relationship found for table <表名> - 跨表查询的连接和聚合粒度由指标所在表驱动,关系建模直接影响结果正确性。详见语义视图关系建模与聚合粒度。
DDL 与管理
- 支持
:可原子替换同名视图定义,无需先CREATE OR REPLACE SEMANTIC VIEW
,重放脚本天然幂等。DROP - 支持
:返回完整、可重放的SHOW CREATE SEMANTIC VIEW <视图名>
DDL(含CREATE
/TABLES
/DIMENSIONS
及METRICS
)。WITH SYNONYMS
等其他元数据不进 DDL,用enum_values
查看(注意DESC EXTENDED
/is_unique
回读值不保真,见"元数据子句")。is_time
支持ALTER SEMANTIC VIEW
、RENAME TO
、SET PROPERTIES
,但不支持直接增删维度/指标(UNSET PROPERTIES
、ADD/DROP DIMENSION
报语法错误)。需要增删维度/指标时用ADD/DROP METRIC
重放完整定义。CREATE OR REPLACE
的新名称不能带 schema 前缀(带前缀报语法错误)。RENAME TO- 没有
函数、YAML 导出;GET_DDL
/DESC SEMANTIC VIEW
命令存在但返回空,DESCRIBE SEMANTIC VIEW
(不加DESC
)也返回空。回读结构用EXTENDED
(DDL 文本)或SHOW CREATE SEMANTIC VIEW
(结构化,含全量元数据)。DESC EXTENDED
创建行为
子句必填,TABLES
和DIMENSIONS
均可选(仅METRICS
也能创建成功)。TABLES- 视图已存在时
报CREATE SEMANTIC VIEW
;用already exists
跳过,或先执行IF NOT EXISTS
保证脚本幂等。DROP SEMANTIC VIEW IF EXISTS - 外键列与被引用列数据类型必须一致,否则报错,例如:
跨表指标与粒度
外键定义了逻辑表的一对多关系:被引用方是父表(粒度更粗),引用方是子表(粒度更细)。指标的聚合可以作用于自己表的列(单层聚合),也可以对更细子表的列做双层聚合。
双层聚合 —— 父表指标对子表列先按父表粒度汇总、再聚合。例如"每个订单的明细金额之和"再求平均:
内层
SUM 把 lineitem 汇总到订单粒度,外层 AVG 再汇总到查询粒度。查询时按父表维度分组即得到正确的上卷(roll-up)结果。
恒等透传(FACTS) —— 父表指标要引用子表的列时,需先在
FACTS 子句把该列声明为逻辑事实,指标再引用这个事实。有两种可行写法:
查询时的分组规则 —— 指标可以按等于或更粗粒度的维度分组(roll-up 上卷),但不能按更细粒度的维度分组(会扇出双重计算)。例如用子表
orders 的维度去分组父表 customer 粒度的指标,引擎会拦截并给出清晰的粒度错误:
去重计数的正确列 —— 统计"去重的父实体数量"时,用子表自己的外键列而不是父表主键:
COUNT(DISTINCT orders.o_custkey) 可行;在 orders 指标里写 COUNT(DISTINCT customer.c_custkey)(父表主键)会报 cannot resolve column。两者去重结果相同,但前者无扇出。
内省命令
除
SHOW SEMANTIC VIEWS 外,还有三条命令返回结构化、每对象一行的元数据,适合 Agent 精确发现"能按什么分组、能聚合什么",无需解析 DDL 文本:
三者返回相同的 9 列:
workspace_name、schema_name、semantic_view_name、table_name、name、data_type、synonyms、comment、access(PUBLIC/PRIVATE)。
- 维度形式加
只返回可合法用于分组该指标的维度(等于或更粗粒度且相关),据此可直接构造粒度安全的FOR METRIC <指标>
查询。semantic_view(...) - 视图未定义某类对象时返回空行(如没有维度时
返回 0 行),属正常。SHOW SEMANTIC DIMENSIONS
对象可见性:PUBLIC 与 PRIVATE
维度、指标、事实可标记为
PUBLIC(默认)或 PRIVATE。PRIVATE 对象不能被直接查询或过滤,只能被组合进其他 PUBLIC 的事实/指标——用于封装中间计算,不暴露给最终查询。
直接查询
PRIVATE 指标报错:
SHOW SEMANTIC METRICS / DIMENSIONS / FACTS 的 access 列会显示每个对象是 PUBLIC 还是 PRIVATE(见"内省命令")。
权限模型
语义视图只支持只读权限。
(或GRANT SELECT
,等同于 SELECT)可授予角色查询权限;创建者自动拥有ALL
。ALL- 不支持
/INSERT
/UPDATE
,DELETE
报GRANT INSERT ON SEMANTIC VIEW ...
。invalid action type INSERT
查看授权,返回列:SHOW GRANTS ON SEMANTIC VIEW <名称>
、granted_type
、privilege
、conditions
(值为granted_on
)、SEMANTIC_VIEW
、object_name
、granted_to
、grantee_name
、grantor_name
、grant_option
。granted_time
限制速查表
| 能力 | 状态 | 说明 / 报错 |
|---|---|---|
| 通用聚合函数(DISTINCT/STDDEV/MEDIAN/PERCENTILE/GROUP_CONCAT 等) | 支持 | 不限于 COUNT/SUM/AVG/MIN/MAX |
| 算术表达式指标(MAX-MIN、SUM/COUNT 等) | 支持 | 单独查、混查结果均正确 |
| 派生指标(同表相除 / 引用命名指标) | 支持 | 指标体内相除,或引用同表已命名指标 |
| 条件指标 FILTER (WHERE ...) | 支持 | 多个过滤指标可并列查询 |
| 双层聚合(父表聚合子表列) | 支持 | AVG(SUM(子表.列)) |
| 恒等透传 FACTS | 支持 | 父表指标引用子表列的前置声明 |
| NULL 处理 | 标准 SQL 语义 | NULL 维度单独成组;聚合跳过 NULL;零除返回 NULL |
| SYNONYMS / enum_values 回读 | 保真 | 进 DESC EXTENDED,值与创建一致 |
| is_unique / is_time 回读 | 值不保真 | 声明即回读 true,不反映实际值 |
| CREATE OR REPLACE | 支持 | 原子替换,脚本幂等 |
| SHOW CREATE SEMANTIC VIEW | 支持 | 返回可重放 DDL |
| SHOW SEMANTIC DIMENSIONS/METRICS/FACTS | 支持 | 9 列,含 access;维度支持 FOR METRIC |
| PUBLIC / PRIVATE 对象可见性 | 支持 | PRIVATE 只能被组合,不能直接查 |
| 窗口函数指标(RANK/占比/累计等) | 支持 | PARTITION BY/ORDER BY 用维度限定名、同表、查询须含该维度 |
| 跨表指标相除(引用他表列) | 不支持 | 报 cannot resolve column |
| 细维度分组粗指标(下钻) | 拦截报错 | invalid dimension ... finer grain(防扇出) |
| chasm trap(兄弟分支指标组合) | 拦截报错 | No relationship found for table … |
| ALTER 增删维度/指标 | 不支持 | 用 CREATE OR REPLACE 重放;RENAME TO 不能带 schema 前缀 |
| 仅 TABLES 创建 | 支持 | DIMENSIONS / METRICS 可选 |
| 权限 | 只读 | SELECT / ALL;无 INSERT / UPDATE / DELETE |
排错速查(按症状)
遇到报错或结果不对时,按下面的症状定位原因。
| 症状 / 报错 | 原因 | 对策 |
|---|---|---|
窗口指标报 | PARTITION BY/ORDER BY 用了物理列名或裸别名 | 改用维度限定别名,如 |
窗口指标报 | 查询未把 PARTITION BY/ORDER BY 的维度放进 DIMENSIONS | 在 的 DIMENSIONS 中带上该维度 |
创建报 (指标聚合父表列) | 指标聚合了更粗父表的列 | 只聚合自己表或更细子表的列;跨表引用子表列先用 FACTS 透传 |
创建报 | 外键列与被引用列类型不一致 | 改用类型一致的列,或显式指定引用列 |
查询报 | 用更细粒度的维度分组更粗粒度的指标(下钻) | 只用等于或更粗粒度的维度分组,或去掉该维度 |
查询报 | 组合了两个无直接关系路径的分支指标(chasm trap) | 拆成多次查询,每次只取一条关系链上的指标 |
查询报 | 没传任何 DIMENSIONS/METRICS/FACTS | 至少指定一个维度、指标或事实 |
创建报 | 视图已存在且未用替换语法 | 用 ,或加 |
查询报 | 直接查询了 PRIVATE 对象 | PRIVATE 只能被组合进 PUBLIC 对象,改查 PUBLIC 指标 |
返回空 | 没加 ,或用了 | 用 或 |
返回空 | 不支持 过滤 | 去掉 LIKE,全列后自行筛选 |
| 跨表指标数值偏大/重复 | 手写 JOIN 导致扇出双重计算 | 用语义视图自动按指标粒度聚合,不要手写 JOIN |
| 维度成员缺失(如某客户不出现) | 该成员在指标表里没有事实行 | 需要全集时直接查维度表,详见关系建模与聚合粒度 |
