创建语义视图
语法
CREATE [ OR REPLACE ] SEMANTIC VIEW [ IF NOT EXISTS ] <视图名称>
TABLES (
<逻辑表定义> [ , ... ]
)
[ RELATIONSHIPS (
<关系定义> [ , ... ]
) ]
[ VARIABLES (
<变量定义> [ , ... ]
) ]
[ FACTS (
<事实定义> [ , ... ]
) ]
[ DIMENSIONS (
<维度定义> [ , ... ]
) ]
[ METRICS (
<指标定义> [ , ... ]
) ]
[ COMMENT = '<视图说明>' ]
;
⚠️ 注意 :子句顺序固定为
TABLES → RELATIONSHIPS → VARIABLES → FACTS → DIMENSIONS → METRICSTABLES → RELATIONSHIPS → VARIABLES → FACTS → DIMENSIONS → METRICS
,写乱会报
Syntax error at or near '<子句名>'Syntax error at or near '<子句名>'
(例如把
VARIABLESVARIABLES
写在
RELATIONSHIPSRELATIONSHIPS
之前、或
FACTSFACTS
写在
DIMENSIONSDIMENSIONS
之后)。
💡 提示 :外键关系有两种等价写法——写在逻辑表内的内联
FOREIGN KEYFOREIGN KEY
(见下方逻辑表定义),或独立的顶层
RELATIONSHIPSRELATIONSHIPS
子句。两者创建时都接受,
DESC EXTENDEDDESC EXTENDED
/
SHOW CREATE SEMANTIC VIEWSHOW CREATE SEMANTIC VIEW
回读时统一规范化为
RELATIONSHIPSRELATIONSHIPS
子句。
CREATE ... IF NOT EXISTSCREATE ... IF NOT EXISTS
在视图已存在时静默跳过、不报错(与
OR REPLACEOR REPLACE
互斥,不要同时写)。
各子句的定义语法如下:
逻辑表定义
<表别名> AS <架构名>.<物理表名>
PRIMARY KEY ( <列名> [ , ... ] )
[ FOREIGN KEY ( <列名> ) REFERENCES <其他逻辑表别名> [ ( <引用列名> ) ] ]
[ WITH SYNONYMS ( '<同义词>' [ , ... ] ) ]
[ COMMENT = '<说明>' ]
关系定义
<引用表别名> ( <外键列> [ , ... ] ) REFERENCES <被引用表别名> [ ( <引用列> [ , ... ] ) ]
RELATIONSHIPSRELATIONSHIPS
是声明外键关系的独立顶层子句,与写在逻辑表内的内联
FOREIGN KEYFOREIGN KEY
等价——同一份关系既可内联,也可集中写在
RELATIONSHIPSRELATIONSHIPS
里。回读(
SHOW CREATE SEMANTIC VIEWSHOW CREATE SEMANTIC VIEW
/
DESC EXTENDEDDESC EXTENDED
)时统一规范化为
RELATIONSHIPSRELATIONSHIPS
形式。外键列与被引用列的数据类型必须一致,列名不同时需显式写出引用列。复合外键在括号内按顺序列出多列。
变量定义
<变量名> <数据类型> [ { DEFAULT | = } <默认值> ] [ COMMENT = '<说明>' ]
VARIABLESVARIABLES
声明
查询参数 :维度、指标表达式里引用这个变量名,查询时可用
semantic_view()semantic_view()
的
VARIABLESVARIABLES
子句为它绑定值,实现同一视图按不同阈值/口径取数。
DEFAULTDEFAULT
与
==
等价(都持久化为
DEFAULTDEFAULT
);不写默认值的变量,只要被维度/指标引用,查询时就必须绑定。绑定方式见
查询语义视图 的"查询时绑定 VARIABLES"。
事实定义
[ PRIVATE ] <逻辑表别名>.<事实名> AS { <列表达式> | <聚合表达式> }
FACTSFACTS
声明逻辑事实,主要用于
父表指标引用子表的列 :父表指标不能直接聚合子表列,需先在
FACTSFACTS
里把子表列声明为事实(恒等透传),指标再引用这个事实。详见
能力与限制参考 的"跨表指标与粒度"。
维度定义
[ PRIVATE ] { <逻辑表别名>.<维度名> | <维度名> } AS <表达式>
[ WITH SYNONYMS = ( '<同义词>' [ , ... ] ) ]
[ is_unique = { true | false } ]
[ is_time = { true | false } ]
[ enum_values = [ <值1>, <值2>, ... ] ]
[ COMMENT = '<说明>' ]
指标定义
[ PRIVATE ] <逻辑表别名>.<指标名> AS <聚合表达式>
[ COMMENT = '<说明>' ]
PRIVATEPRIVATE
修饰符(默认
PUBLICPUBLIC
)标记该维度/指标/事实只能被组合进其他
PUBLICPUBLIC
对象,不能被直接查询或过滤,用于封装中间计算。详见
能力与限制参考 的"对象可见性"。
参数说明
逻辑表参数
参数 说明 <表别名> AS <架构名>.<物理表名><表别名> AS <架构名>.<物理表名>
为物理表指定逻辑别名,后续维度、指标、外键定义均使用此别名 PRIMARY KEY ( <列名> )PRIMARY KEY ( <列名> )
指定主键列,用于确定表间关系类型 FOREIGN KEY ( <列名> ) REFERENCES <别名> [ ( <引用列名> ) ]FOREIGN KEY ( <列名> ) REFERENCES <别名> [ ( <引用列名> ) ]
定义外键关系。当外键列与被引用表主键列名不同时,需显式指定引用列名。外键列与引用列数据类型必须一致 ,否则创建报错 WITH SYNONYMS ( '<同义词>' )WITH SYNONYMS ( '<同义词>' )
为逻辑表定义同义词,增强可发现性 COMMENT = '<说明>'COMMENT = '<说明>'
逻辑表描述
维度参数
参数 说明 is_unique = trueis_unique = true
声明该维度值唯一,如客户名称(声明性标注,当前无 SQL 层效果) is_time = trueis_time = true
声明该维度为时间类型,如订单日期(声明性标注,当前无 SQL 层效果) enum_values = [...]enum_values = [...]
声明维度的取值范围(声明性标注,不做输入校验 ,越界值照常返回) WITH SYNONYMS = (...)WITH SYNONYMS = (...)
为维度定义同义词,支持多种业务术语引用同一维度
事实参数
参数 说明 <别名>.<事实名> AS <列表达式><别名>.<事实名> AS <列表达式>
恒等透传:把子表的列声明为逻辑事实(别名可与物理列不同名),供父表指标引用。父表指标不能直接聚合子表列,透传后即可引用 <别名>.<事实名> AS <聚合表达式><别名>.<事实名> AS <聚合表达式>
在 FACTSFACTS
内直接定义组合聚合(如 COUNT(...)COUNT(...)
),查询时用 FACTSFACTS
关键字选取 PRIVATEPRIVATE
标记事实只能被组合进其他 PUBLICPUBLIC
对象,不能被直接查询
变量参数
参数 说明 <变量名> <数据类型><变量名> <数据类型>
声明一个查询参数(如 min_amount decimal(12,2)min_amount decimal(12,2)
)。维度/指标表达式用裸变量名引用它(区别于 别名.列别名.列
形式的物理列)。不带默认值时,被引用就必须在查询时绑定,否则报错 DEFAULT <默认值>DEFAULT <默认值>
/ = <默认值>= <默认值>
指定默认值,查询不绑定时用它。两种写法等价,均持久化为 DEFAULTDEFAULT
。默认值必须是常量 COMMENT = '<说明>'COMMENT = '<说明>'
变量描述
可见性参数
参数 说明 PUBLICPUBLIC
(默认)维度/指标/事实可被直接查询和过滤 PRIVATEPRIVATE
只能被组合进其他 PUBLICPUBLIC
对象,直接查询报 is PRIVATE and cannot be selected or filtered directlyis PRIVATE and cannot be selected or filtered directly
。用于封装中间计算,不暴露给最终查询
指标聚合函数
支持 :
通用聚合函数,不限于 COUNTCOUNT
/SUMSUM
/AVGAVG
/MINMIN
/MAXMAX
,还包括 COUNT(DISTINCT ...)COUNT(DISTINCT ...)
、APPROX_COUNT_DISTINCTAPPROX_COUNT_DISTINCT
、STDDEVSTDDEV
、VARIANCEVARIANCE
、MEDIANMEDIAN
、PERCENTILEPERCENTILE
、GROUP_CONCATGROUP_CONCAT
等。
条件聚合,如 COUNT(CASE WHEN col = value THEN 1 END)COUNT(CASE WHEN col = value THEN 1 END)
,以及 <聚合函数>(...) FILTER (WHERE <条件>)<聚合函数>(...) FILTER (WHERE <条件>)
。
算术表达式指标:MAX(col) - MIN(col)MAX(col) - MIN(col)
、SUM(col) / COUNT(col)SUM(col) / COUNT(col)
等,可直接写在指标体内。
派生指标:同一逻辑表内引用其他已命名指标做运算,如 emps.avg AS emps.total_salary / emps.total_employeesemps.avg AS emps.total_salary / emps.total_employees
。
窗口函数指标:RANK()RANK()
/ROW_NUMBER()ROW_NUMBER()
等排名,或 SUM(SUM(...)) OVER (...)SUM(SUM(...)) OVER (...)
这类聚合套窗口做占比、累计(示例见下方"带窗口函数指标的语义视图")。PARTITION BYPARTITION BY
/ORDER BYORDER BY
须引用维度的限定别名(如 orders.regionorders.region
),受同表约束,且查询时该维度须出现在 DIMENSIONSDIMENSIONS
中。
不支持 :
跨表指标相除:指标体只能引用自己所在表(及更细子表)的列,引用无关表的列报 cannot resolve columncannot resolve column
。跨表的复合计算请放到 semantic_view()semantic_view()
查询的外层 SQL 中完成。
使用说明
TABLESTABLES
子句是必须的,不可省略。RELATIONSHIPSRELATIONSHIPS
、VARIABLESVARIABLES
、FACTSFACTS
、DIMENSIONSDIMENSIONS
、METRICSMETRICS
均为可选,但出现时必须按 RELATIONSHIPS → VARIABLES → FACTS → DIMENSIONS → METRICSRELATIONSHIPS → VARIABLES → FACTS → DIMENSIONS → METRICS
的顺序书写。
CREATE OR REPLACE SEMANTIC VIEWCREATE OR REPLACE SEMANTIC VIEW
可原子替换同名视图定义,无需先 DROPDROP
,适合改结构时重放完整定义。
被外键引用的逻辑表必须在 TABLESTABLES
子句中先于引用方定义。
视图已存在时 CREATE SEMANTIC VIEWCREATE SEMANTIC VIEW
报错,建议先执行 DROP SEMANTIC VIEW IF EXISTSDROP SEMANTIC VIEW IF EXISTS
。
维度支持表达式(计算维度),如 YEAR(hire_date)YEAR(hire_date)
,查询结果返回整数类型。
维度和指标命名支持限定名称 (alias.namealias.name
)和短名称 (namename
)两种形式,名称唯一时两者等效。
WITH SYNONYMSWITH SYNONYMS
、is_uniqueis_unique
、is_timeis_time
、enum_valuesenum_values
这些维度元数据子句会持久化并可通过 DESC EXTENDEDDESC EXTENDED
回读(其中 synonymssynonyms
、enum_valuesenum_values
值保真;is_uniqueis_unique
、is_timeis_time
只反映是否声明过,写了即回读 truetrue
)。它们主要面向上层 AI/元数据工具,在纯 SQL 查询链路里不影响结果。
需要过滤时有三种方式:① 用 FILTER (WHERE ...)FILTER (WHERE ...)
条件聚合指标,把过滤口径持久化进视图定义(见下方示例);② 在 semantic_view()semantic_view()
内部 用结尾 WHEREWHERE
子句过滤维度(排在 DIMENSIONSDIMENSIONS
/METRICSMETRICS
/FACTSFACTS
之后、VARIABLESVARIABLES
之前,维度限定名或短名均可);③ 在 semantic_view()semantic_view()
外层 用 WHEREWHERE
过滤,此处只能用维度短名(写 emps.departmentemps.department
会报 cannot resolve columncannot resolve column
)。方式 ② ③ 的查询语法和示例见查询语义视图 。
示例
前置准备
本章节多篇文档(查询语义视图 、高级查询用法 、与 AI 功能集成 等)的示例都基于下面这套
doc_test.employeesdoc_test.employees
和
doc_test.departmentsdoc_test.departments
表,先建表并插入数据:
CREATE TABLE doc_test.departments (
dept_id INT,
dept_name STRING,
manager STRING
);
CREATE TABLE doc_test.employees (
id INT,
name STRING,
dept STRING,
salary DECIMAL(12,2),
hire_date DATE,
is_active BOOLEAN
);
INSERT INTO doc_test.departments VALUES
(1, 'Engineering', 'Alice'),
(2, 'Marketing', 'Bob'),
(3, 'HR', 'Carol');
INSERT INTO doc_test.employees VALUES
(1, 'Emp_A', 'Engineering', 130000, DATE'2019-01-01', true),
(2, 'Emp_B', 'Engineering', 100000, DATE'2020-01-01', true),
(3, 'Emp_C', 'Marketing', 95000, DATE'2021-01-01', true),
(4, 'Emp_D', 'Marketing', 90000, DATE'2022-01-01', true),
(5, 'Emp_E', 'HR', 80000, DATE'2023-01-01', true);
数据特征:Engineering 2 人(薪资 130000、100000,均值 115000)、Marketing 2 人(95000、90000,均值 92500)、HR 1 人(80000);5 人分别入职于 2019–2023 年。后续查询示例的输出均基于这套数据。
基础示例:单表语义视图
基于上面的前置数据创建语义视图:
DROP SEMANTIC VIEW IF EXISTS doc_test.emp_dept_analysis;
CREATE SEMANTIC VIEW doc_test.emp_dept_analysis
TABLES (
depts AS doc_test.departments
PRIMARY KEY (dept_name),
emps AS doc_test.employees
PRIMARY KEY (id)
FOREIGN KEY (dept) REFERENCES depts (dept_name)
)
DIMENSIONS (
emps.employee_name AS emps.name
WITH SYNONYMS = ('员工姓名', 'staff name')
is_unique = true
COMMENT = '员工姓名',
emps.department AS emps.dept
COMMENT = '所在部门',
emps.hire_year AS YEAR(emps.hire_date)
is_time = true
COMMENT = '入职年份',
depts.manager_name AS depts.manager
COMMENT = '部门经理'
)
METRICS (
emps.total_employees AS COUNT(emps.id)
COMMENT = '员工总数',
emps.avg_salary AS AVG(emps.salary)
COMMENT = '平均薪资',
emps.max_salary AS MAX(emps.salary)
COMMENT = '最高薪资'
)
COMMENT = '员工部门分析语义视图';
说明:
带维度元数据的语义视图
以下示例展示了
is_uniqueis_unique
、
is_timeis_time
、
enum_valuesenum_values
等维度元数据,以及
WITH SYNONYMSWITH SYNONYMS
子句的写法。这些元数据子句的回读行为见上方使用说明。前置数据:
CREATE TABLE doc_test.doc_meta_cust (c_custkey INT, c_name STRING);
CREATE TABLE doc_test.doc_meta_ord (
o_orderkey INT,
o_custkey INT,
o_totalprice DECIMAL(12,2),
o_orderdate DATE
);
INSERT INTO doc_test.doc_meta_cust VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Carol');
INSERT INTO doc_test.doc_meta_ord VALUES
(101, 1, 250.00, DATE'2025-01-15'), (102, 1, 150.00, DATE'2025-06-20'),
(103, 2, 300.00, DATE'2025-06-05'), (104, 3, 500.00, DATE'2025-12-10');
DROP SEMANTIC VIEW IF EXISTS doc_test.sv_metadata;
CREATE SEMANTIC VIEW doc_test.sv_metadata
TABLES (
customers AS doc_test.doc_meta_cust
PRIMARY KEY (c_custkey)
COMMENT = '客户主表',
orders AS doc_test.doc_meta_ord
PRIMARY KEY (o_orderkey)
FOREIGN KEY (o_custkey) REFERENCES customers
WITH SYNONYMS ('sales orders')
COMMENT = '销售订单表'
)
DIMENSIONS (
customers.customer_name AS customers.c_name
WITH SYNONYMS = ('客户名称', 'customer name')
is_unique = true
COMMENT = '客户名称',
orders.order_date AS orders.o_orderdate
is_time = true
enum_values = [date'2025-01-01', date'2025-06-01', date'2025-12-01']
COMMENT = '下单日期',
orders.order_year AS YEAR(orders.o_orderdate)
COMMENT = '下单年份'
)
METRICS (
customers.customer_count AS COUNT(customers.c_custkey)
COMMENT = '客户数',
orders.order_average_value AS AVG(orders.o_totalprice)
COMMENT = '平均订单金额'
)
COMMENT = '收入分析语义视图';
DESC EXTENDED doc_test.sv_metadataDESC EXTENDED doc_test.sv_metadata
回读时,元数据均保真:
customer_namecustomer_name
的
synonymssynonyms
为
客户名称,customer name客户名称,customer name
、
is_uniqueis_unique
为
truetrue
,
order_dateorder_date
的
is_timeis_time
为
truetrue
、
enum_valuesenum_values
为
2025-01-01,2025-06-01,2025-12-012025-01-01,2025-06-01,2025-12-01
(date 字面量按日期值回读)。
⚠️ 注意 :
customer_countcustomer_count
定义在父表
customerscustomers
,不能按更细粒度的子表
ordersorders
维度(如
order_yearorder_year
)分组——会报
invalid dimension ... finer graininvalid dimension ... finer grain
(下钻非法)。父表指标只能按等于或更粗粒度的维度分组,如按
customer_namecustomer_name
查客户数、按
order_yearorder_year
查
order_average_valueorder_average_value
(orders 同表指标)。粒度规则详见
关系建模与聚合粒度 。
带 FACTS 的语义视图(父表引用子表列)
父表(
customercustomer
)的指标要基于子表(
ordersorders
)的列聚合时,直接在指标里写
COUNT(orders.o_orderkey)COUNT(orders.o_orderkey)
会因粒度不匹配失败。先在
FACTSFACTS
里把子表列透传为逻辑事实,指标再引用这个事实。前置数据:
CREATE TABLE doc_test.fct_cust (c_custkey INT, c_name STRING);
CREATE TABLE doc_test.fct_ord (o_orderkey INT, o_custkey INT, o_totalprice DECIMAL(12,2));
INSERT INTO doc_test.fct_cust VALUES (1, 'Alice'), (2, 'Bob');
INSERT INTO doc_test.fct_ord VALUES
(101, 1, 250.00), (102, 1, 150.00), (103, 2, 300.00);
CREATE SEMANTIC VIEW doc_test.sv_facts
TABLES (
customer AS doc_test.fct_cust
PRIMARY KEY (c_custkey),
orders AS doc_test.fct_ord
PRIMARY KEY (o_orderkey)
FOREIGN KEY (o_custkey) REFERENCES customer
)
FACTS (
orders.order_id AS o_orderkey -- 透传子表列,别名与物理列不同名
)
DIMENSIONS (
customer.cust_name AS c_name
)
METRICS (
customer.order_count AS COUNT(orders.order_id) -- 父表指标引用透传的事实
);
按客户名查询订单数,得到正确的上卷结果(Alice 2 笔、Bob 1 笔)。FACTS 的两种写法、双层聚合和粒度规则详见能力与限制参考 的"跨表指标与粒度"。
带查询参数(VARIABLES)的语义视图
VARIABLESVARIABLES
声明查询参数:把维度/指标里的阈值、口径抽成一个命名变量,查询时按需绑定不同的值,同一视图适配多套口径,无需为每个阈值单独建视图。下例把"销售额高低分界线"定义成变量
min_amountmin_amount
(默认 1000),维度
sale_categorysale_category
用它把销售额分成 HIGH / LOW。前置数据:
CREATE TABLE doc_test.doc_var_sales (
sale_id INT,
amount DECIMAL(12,2)
);
INSERT INTO doc_test.doc_var_sales VALUES (1, 500.00), (2, 1500.00), (3, 2500.00);
CREATE OR REPLACE SEMANTIC VIEW doc_test.sv_variables
TABLES (
sales AS doc_test.doc_var_sales
PRIMARY KEY (sale_id)
)
VARIABLES (
min_amount DECIMAL(12,2) DEFAULT 1000.00 COMMENT 'HIGH/LOW 阈值'
)
DIMENSIONS (
sales.sale_category AS CASE WHEN sales.amount >= min_amount THEN 'HIGH' ELSE 'LOW' END
)
METRICS (
sales.total_sales AS SUM(sales.amount)
);
维度表达式里的
min_amountmin_amount
是裸变量名(不带
别名.别名.
前缀),引擎据此识别为变量而非物理列。不绑定时用默认值 1000:
amount >= 1000amount >= 1000
的记录(1500、2500)归 HIGH,合计 4000;其余(500)归 LOW。查询时绑定其它阈值即可切换分界线,绑定语法见
查询语义视图 的"查询时绑定 VARIABLES"。
⚠️ 注意 :
VARIABLESVARIABLES
子句必须排在
TABLESTABLES
(及可选的
RELATIONSHIPSRELATIONSHIPS
)之后、
FACTSFACTS
/
DIMENSIONSDIMENSIONS
/
METRICSMETRICS
之前。写在后面会报
Syntax error at or near 'VARIABLES'Syntax error at or near 'VARIABLES'
。
带条件聚合的语义视图(分段 KPI)
同一个度量常需要按不同口径拆分——总收入、仅未完成订单收入、仅已完成订单收入。用
<聚合函数>(...) FILTER (WHERE <条件>)<聚合函数>(...) FILTER (WHERE <条件>)
把每个口径定义成独立指标,每个指标的过滤条件互相独立,可在同一次查询里并列取用。前置数据:
CREATE TABLE doc_test.doc_filt_orders (
o_orderkey INT,
o_region STRING,
o_totalprice DECIMAL(12,2),
o_status STRING
);
INSERT INTO doc_test.doc_filt_orders VALUES
(101, 'East', 250.00, 'O'), (102, 'East', 150.00, 'F'),
(103, 'East', 300.00, 'O'), (104, 'West', 500.00, 'F'),
(105, 'West', 200.00, 'O');
CREATE SEMANTIC VIEW doc_test.sv_conditional
TABLES (
orders AS doc_test.doc_filt_orders
PRIMARY KEY (o_orderkey)
)
DIMENSIONS (
orders.region AS orders.o_region
)
METRICS (
orders.total_revenue AS SUM(orders.o_totalprice)
COMMENT = '全部订单收入',
orders.open_revenue AS SUM(orders.o_totalprice) FILTER (WHERE orders.o_status = 'O')
COMMENT = '仅未完成(O)订单收入',
orders.done_revenue AS SUM(orders.o_totalprice) FILTER (WHERE orders.o_status = 'F')
COMMENT = '仅已完成(F)订单收入'
);
按地区查询,三个口径一次取回:
SELECT * FROM semantic_view(
doc_test.sv_conditional
DIMENSIONS orders.region
METRICS orders.total_revenue, orders.open_revenue, orders.done_revenue
) ORDER BY region;
+--------+---------------+--------------+--------------+
| region | total_revenue | open_revenue | done_revenue |
+--------+---------------+--------------+--------------+
| East | 700.00 | 550.00 | 150.00 |
| West | 700.00 | 200.00 | 500.00 |
+--------+---------------+--------------+--------------+
每个
FILTER (WHERE ...)FILTER (WHERE ...)
只对满足条件的行聚合,
open_revenueopen_revenue
与
done_revenuedone_revenue
之和等于
total_revenuetotal_revenue
。
💡 提示 :
FILTER (WHERE ...)FILTER (WHERE ...)
是标准 SQL 的条件聚合,写在指标体内、随视图定义持久化。等价写法还有
SUM(CASE WHEN o_status = 'O' THEN o_totalprice END)SUM(CASE WHEN o_status = 'O' THEN o_totalprice END)
。
带算术与派生指标的语义视图
指标体可以直接写算术表达式(如
MAX(...) - MIN(...)MAX(...) - MIN(...)
),也可以在同一逻辑表内引用其他已命名指标做运算(派生指标,如用总额除以人数得平均值)。前置数据:
CREATE TABLE doc_test.doc_arith_emp (
id INT,
dept STRING,
salary DECIMAL(12,2)
);
INSERT INTO doc_test.doc_arith_emp VALUES
(1, 'Engineering', 130000), (2, 'Engineering', 100000),
(3, 'Marketing', 95000), (4, 'Marketing', 90000),
(5, 'HR', 80000);
CREATE SEMANTIC VIEW doc_test.sv_arith
TABLES (
emps AS doc_test.doc_arith_emp
PRIMARY KEY (id)
)
DIMENSIONS (
emps.department AS emps.dept
)
METRICS (
emps.total_salary AS SUM(emps.salary),
emps.headcount AS COUNT(emps.id),
emps.salary_range AS MAX(emps.salary) - MIN(emps.salary), -- 算术表达式指标
emps.avg_salary AS emps.total_salary / emps.headcount -- 派生指标:引用同表其他指标
);
SELECT * FROM semantic_view(
doc_test.sv_arith
DIMENSIONS emps.department
METRICS emps.total_salary, emps.headcount, emps.salary_range, emps.avg_salary
) ORDER BY department;
+-------------+--------------+-----------+--------------+----------------------------+
| department | total_salary | headcount | salary_range | avg_salary |
+-------------+--------------+-----------+--------------+----------------------------+
| Engineering | 230000.00 | 2 | 30000.00 | 115000.000000000000000000 |
| HR | 80000.00 | 1 | 0.00 | 80000.000000000000000000 |
| Marketing | 185000.00 | 2 | 5000.00 | 92500.000000000000000000 |
+-------------+--------------+-----------+--------------+----------------------------+
salary_rangesalary_range
是同表两个聚合相减;
avg_salaryavg_salary
引用了本视图已定义的
total_salarytotal_salary
和
headcountheadcount
相除。派生指标只能引用
同一逻辑表 内的其他指标。
💡 提示 :
avg_salaryavg_salary
是 decimal 相除,结果按 decimal 除法规则扩展到高精度小数位(如
115000.000000000000000000115000.000000000000000000
)。需要固定小数位时,在指标体或外层查询用
ROUND(...)ROUND(...)
。
带 PRIVATE 中间指标的语义视图
PRIVATEPRIVATE
把中间计算量封装起来:它能被其他
PUBLICPUBLIC
指标组合引用,但不能被直接查询。适合只想暴露最终口径(如毛利率),隐藏中间量(总收入、总成本)的场景。前置数据:
CREATE TABLE doc_test.doc_priv_sales (
id INT,
region STRING,
revenue DECIMAL(12,2),
cost DECIMAL(12,2)
);
INSERT INTO doc_test.doc_priv_sales VALUES
(1, 'East', 1000.00, 600.00),
(2, 'East', 500.00, 300.00),
(3, 'West', 800.00, 500.00);
CREATE SEMANTIC VIEW doc_test.sv_private
TABLES (
sales AS doc_test.doc_priv_sales
PRIMARY KEY (id)
)
DIMENSIONS (
sales.region AS sales.region
)
METRICS (
PRIVATE sales.total_rev AS SUM(sales.revenue),
PRIVATE sales.total_cost AS SUM(sales.cost),
sales.margin_pct AS (sales.total_rev - sales.total_cost) * 100.0 / sales.total_rev
);
查询
PUBLICPUBLIC
的
margin_pctmargin_pct
正常返回(毛利率在每个分组按"总利润 / 总收入"重算):
SELECT * FROM semantic_view(
doc_test.sv_private
DIMENSIONS sales.region
METRICS sales.margin_pct
) ORDER BY region;
+--------+-----------------+
| region | margin_pct |
+--------+-----------------+
| East | 40.00000000000 |
| West | 37.50000000000 |
+--------+-----------------+
(
margin_pctmargin_pct
是 decimal 相除,返回高精度小数;需要两位百分比时外层套
ROUND(margin_pct, 2)ROUND(margin_pct, 2)
。)
直接查询
PRIVATEPRIVATE
指标会被拒绝:
SELECT * FROM semantic_view(
doc_test.sv_private
DIMENSIONS sales.region
METRICS sales.total_rev
);
CZLH-42000: METRICS 'sales.total_rev' is PRIVATE and cannot be selected or filtered
directly; it may only be composed into a PUBLIC fact/metric
💡 提示 :
PRIVATEPRIVATE
同样适用于维度和
FACTSFACTS
(写在
PRIVATE <别名>.<名称>PRIVATE <别名>.<名称>
处)。用它封装不希望最终用户直接查询的中间量。
带窗口函数指标的语义视图
指标体内可以使用窗口函数做占比、累计、排名。下例用
SUM(SUM(...)) OVER (PARTITION BY ...)SUM(SUM(...)) OVER (PARTITION BY ...)
计算每个订单占其所在大区的收入比。关键约束:
PARTITION BYPARTITION BY
必须写维度的
限定别名 (
orders.regionorders.region
),不能写物理列名;查询时
regionregion
维度也必须出现在
DIMENSIONSDIMENSIONS
中。前置数据:
CREATE TABLE doc_test.doc_win_orders (
o_orderkey INT,
o_region STRING,
o_totalprice DECIMAL(12,2)
);
INSERT INTO doc_test.doc_win_orders VALUES
(101, 'East', 250.00), (102, 'East', 150.00), (103, 'East', 100.00),
(104, 'West', 400.00), (105, 'West', 600.00);
CREATE SEMANTIC VIEW doc_test.sv_window
TABLES (
orders AS doc_test.doc_win_orders
PRIMARY KEY (o_orderkey)
)
DIMENSIONS (
orders.region AS orders.o_region,
orders.orderkey AS orders.o_orderkey
)
METRICS (
orders.revenue AS SUM(orders.o_totalprice),
orders.pct_of_region AS SUM(orders.o_totalprice) * 100.0
/ SUM(SUM(orders.o_totalprice)) OVER (PARTITION BY orders.region)
);
查询时把
regionregion
(
PARTITION BYPARTITION BY
用到的维度)和
orderkeyorderkey
一起放进
DIMENSIONSDIMENSIONS
:
SELECT * FROM semantic_view(
doc_test.sv_window
DIMENSIONS orders.region, orders.orderkey
METRICS orders.revenue, orders.pct_of_region
) ORDER BY region, orderkey;
+--------+----------+---------+------------------+
| region | orderkey | revenue | pct_of_region |
+--------+----------+---------+------------------+
| East | 101 | 250.00 | 50.000000000000 |
| East | 102 | 150.00 | 30.000000000000 |
| East | 103 | 100.00 | 20.000000000000 |
| West | 104 | 400.00 | 40.000000000000 |
| West | 105 | 600.00 | 60.000000000000 |
+--------+----------+---------+------------------+
每个大区内各订单占比合计 100%(East 50+30+20,West 40+60)。
pct_of_regionpct_of_region
同样是 decimal 相除的高精度结果,需要固定小数位时外层套
ROUND(...)ROUND(...)
。
⚠️ 注意 :
PARTITION BY orders.regionPARTITION BY orders.region
若写成物理列
o_regiono_region
会报
must reference a declared dimension by its aliasmust reference a declared dimension by its alias
;查询时若不带
regionregion
维度会报
must also be requested as a dimensionmust also be requested as a dimension
。
PARTITION BYPARTITION BY
/
ORDER BYORDER BY
还只能引用指标同表的维度,不能跨表引用父表维度。
多层粒度阶梯语义视图
多张表通过外键串成一条粒度阶梯:父表粗、子表细 ,外键定义在子表上、指向父表主键。下例是经典的 region → customer → orders → lineitem 四层阶梯(地区最粗,明细行最细)。这套结构决定了指标能按哪些维度分组——同一个明细指标可以按任意更粗的层级上卷(roll-up),但父表指标不能直接聚合子表的列。前置数据:
CREATE TABLE doc_test.grain_region (r_regionkey INT, r_name STRING);
CREATE TABLE doc_test.grain_customer (c_custkey INT, c_name STRING, c_regionkey INT);
CREATE TABLE doc_test.grain_orders (o_orderkey INT, o_custkey INT, o_totalprice DECIMAL(12,2));
CREATE TABLE doc_test.grain_lineitem (l_orderkey INT, l_linenumber INT, l_price DECIMAL(12,2));
INSERT INTO doc_test.grain_region VALUES (1, 'East'), (2, 'West');
INSERT INTO doc_test.grain_customer VALUES (1, 'Alice', 1), (2, 'Bob', 1), (3, 'Carol', 2);
INSERT INTO doc_test.grain_orders VALUES (101, 1, 300.00), (102, 1, 200.00), (103, 2, 500.00), (104, 3, 400.00);
INSERT INTO doc_test.grain_lineitem VALUES
(101, 1, 100.00), (101, 2, 200.00), (102, 1, 200.00),
(103, 1, 150.00), (103, 2, 350.00), (104, 1, 400.00);
CREATE OR REPLACE SEMANTIC VIEW doc_test.sv_grain
TABLES (
region AS doc_test.grain_region
PRIMARY KEY (r_regionkey),
customer AS doc_test.grain_customer
PRIMARY KEY (c_custkey)
FOREIGN KEY (c_regionkey) REFERENCES region,
orders AS doc_test.grain_orders
PRIMARY KEY (o_orderkey)
FOREIGN KEY (o_custkey) REFERENCES customer,
lineitem AS doc_test.grain_lineitem
PRIMARY KEY (l_orderkey, l_linenumber)
FOREIGN KEY (l_orderkey) REFERENCES orders
)
DIMENSIONS (
region.region_name AS region.r_name,
customer.customer_name AS customer.c_name,
orders.orderkey AS orders.o_orderkey
)
METRICS (
lineitem.line_revenue AS SUM(lineitem.l_price),
orders.order_amount AS SUM(orders.o_totalprice)
);
💡 提示 :
DESC EXTENDEDDESC EXTENDED
/
SHOW CREATE SEMANTIC VIEWSHOW CREATE SEMANTIC VIEW
回读时,内联的
FOREIGN KEYFOREIGN KEY
会被规范化成独立的
RELATIONSHIPS (...)RELATIONSHIPS (...)
子句(如
lineitem (l_orderkey) REFERENCES orders (o_orderkey)lineitem (l_orderkey) REFERENCES orders (o_orderkey)
),两种写法等价。
明细指标
line_revenueline_revenue
(定义在最细的
lineitemlineitem
表)可以按阶梯上任意更粗的层级分组,引擎自动沿外键 JOIN 上卷。按最粗的
regionregion
分组:
SELECT * FROM semantic_view(
doc_test.sv_grain
DIMENSIONS region.region_name
METRICS lineitem.line_revenue
) ORDER BY region_name;
+-------------+--------------+
| region_name | line_revenue |
+-------------+--------------+
| East | 1000.00 |
| West | 400.00 |
+-------------+--------------+
按中间层
customercustomer
分组,同一指标自动重新聚合到客户粒度:
SELECT * FROM semantic_view(
doc_test.sv_grain
DIMENSIONS customer.customer_name
METRICS lineitem.line_revenue
) ORDER BY customer_name;
+---------------+--------------+
| customer_name | line_revenue |
+---------------+--------------+
| Alice | 500.00 |
| Bob | 500.00 |
| Carol | 400.00 |
+---------------+--------------+
按最细的
ordersorders
分组:
SELECT * FROM semantic_view(
doc_test.sv_grain
DIMENSIONS orders.orderkey
METRICS lineitem.line_revenue
) ORDER BY orderkey;
+----------+--------------+
| orderkey | line_revenue |
+----------+--------------+
| 101 | 300.00 |
| 102 | 200.00 |
| 103 | 500.00 |
| 104 | 400.00 |
+----------+--------------+
同一个
line_revenueline_revenue
在三个层级返回不同的聚合结果,粒度越粗数字越大,全局合计恒为 1400。这就是粒度阶梯的核心:
指标定义一次,按任意父层级自动上卷 。反过来,父表指标不能直接聚合子表列——
customercustomer
表的指标写
SUM(lineitem.l_price)SUM(lineitem.l_price)
会报
cannot resolve columncannot resolve column
,需要先用
FACTSFACTS
把子表列透传上来。完整的粒度规则(上卷合法、下钻非法、无子行的父行 COUNT 返回 NULL 等)详见
关系建模与聚合粒度 。
相关文档