LOD 编写参考¶
本页按编写模型时会遇到的问题组织规则,供写模型、排查报错时查阅。 第一次接触 LOD,请先读理解 LOD,那里讲了概念、四种用法的选择和过滤的基本区别。 示例中的字段名和指标名都来自电商示例。
本页常用的几个说法:
- 基础指标:LOD 声明第一个参数引用的已有指标,比如
fixed(paid_total, orders.user_id)里的paid_total。 - 固定字段:在字段上声明
fixed,结果是可以分组、筛选、再聚合的字段。 - LOD 指标:在指标上声明 include、exclude 或 fixed,结果是查询直接返回的指标。
- 上下文:查询的
context_filter和time_range,限定参与计算的原始记录。 跨表时只传播通过已声明关系或键对应能够读取的条件,见跨表计算。 与之相对的是普通筛选where_sql,它挑选展示行,不缩小固定计算的输入。 - 字段所在表:固定字段定义在哪个数据集上。它决定结果有哪些行,见跨表计算。
基础指标需要满足什么条件¶
基础指标必须是一个数据集上的一个聚合,或该聚合的筛选派生。
支持求和、计数、去重计数、平均、最小值和最大值,对应 SUM、COUNT、带 DISTINCT 的 COUNT、
AVG、MIN、MAX。多数据集模型中的裸 COUNT(*) 需要通过
D-DATASET 声明归属;计数已声明的非空标识字段也能明确归属。
LOD 指标的基础指标也可以由多个这样的聚合组成,即 compose、比值或表达式指标。
这时 LOD 把每个聚合都放到自己的粒度上算,再套用基础指标原来的式子(包括 fill)。所以
在「收入 − 退款」上做 exclude(net_revenue),得到的就是整条查询的收入减去退款,跨两张
事实表也一样;用它做分母就得到占比。
模型里的表达式要把基础指标的整条式子嵌在外层聚合里,比如
SUM(COALESCE(SUM(orders.amount), 0) - COALESCE(SUM(refunds.amount), 0))。
每个聚合按它所属成员的时间轴分桶,和 compose 本身一样;fixed 也在这些时间轴上应用查询的时间范围,
再在细节层次外面套一层 compose 时同样沿用。include 对每个数据集只汇总一次,
所以同一数据集上的聚合落在两条时间轴上时会被拒绝。
基础指标跨多个数据集时,include 先让每个数据集在自己的行上、按展示行和声明的维度算出
各自的聚合,再按这些分组合并,最后套用基础指标的式子。只要有一个数据集有某个分组,它就
是内层的一行。某个数据集在这一行没有数据,它的聚合就是 NULL,和跨事实 compose 在展示
粒度上缺成员时一样,除非基础指标的 fill 把它补上。外层聚合会跳过 NULL:不加 fill 时,
AVG(include(net_revenue, orders.customer_id)) 会漏掉有订单、没有退款的客户;加上
fill: 0,这个客户按「收入 − 0」计入。每个声明的维度都必须是每个数据集自己的列:它属于
其中一个数据集,并通过 D-CONFORM 与其他每个数据集的
一列配对。跨多个数据集时,exclude() 和 fixed() 不能带分组字段,只能对整条查询计算;
需要带分组时,给每个成员各声明 LOD,再组合结果。
固定字段的基础指标始终只能是单个聚合。窗口结果、另一 LOD 指标,以及以它们为成员的
compose,都不能作为基础指标。
基础指标和分组字段也不能依赖 LOD 字段,包括通过普通计算字段间接依赖。
调整定义顺序不能绕过嵌套限制。include 引用的基础指标不能与其所在数据集的字段同名。
固定字段:指定分组后,把结果作为字段使用¶
固定字段使用 fixed:第一个参数是基础指标名,后续参数是固定分组字段,多个字段用逗号分隔。
字段必须属于当前固定字段所在的数据集;省略前缀时也在这里解析,建议显式写出数据集名。
多个字段组成一个联合分组,不能理解成分别按各字段计算。
电商示例中的 fixed(paid_total, orders.user_id) 表示按用户汇总实付。
同表计算可以省略所有分组字段,此时得到整个计算范围的一个值;跨表计算不能省略。
固定字段不能使用 include/exclude,声明本身也不能再包一层聚合。
查询可以读取、分组、筛选或排序该字段,普通计算字段也可以读取它。 当普通指标再次聚合固定字段时,每个展示组内,同一个固定分组只参与一次。 理解 LOD 里广告渠道的用户均值因此按两位买家求平均,不按他们的五笔订单重复加权。 同一对象出现在多个展示组时,在每个组内各参与一次,各组人数不一定可以直接相加。
| 再次聚合时读取什么 | 每一份按什么计算 |
|---|---|
| 原始列或原始行计数 | 原始记录 |
| 固定字段 | 每个展示组内不同的固定分组 |
| 只依赖 LOD 值和常量的计算字段 | 这些 LOD 值的固定分组 |
| 同时读取原始列的计算字段 | 原始记录 |
| 条件读取 LOD 值的筛选指标 | 与基础指标相同;筛选后的行计数仍按原始记录 |
固定字段仅用来分组时,不改变原始行指标的计数方式。
多个不同固定分组的字段可以共同展示或筛选,但一次查询只能对同一组固定分组字段的值再次聚合,
也不能同时请求按原始记录计算的指标。两个指标写出来是同一个表达式时也一样:对行计数加筛选的筛选指标
按原始记录计数,直接写成指标的同一个 CASE WHEN 只读 LOD 值,按固定分组计数。
同表计算中,NULL 分组键有自己的分组,并匹配该组的固定值。 去重计数仍排除 NULL,不能把去重键数当作包含 NULL 组在内的总分组数。 联合分组匹配时保留所有字段。
LOD 指标:把结果直接作为指标返回¶
指标声明的第一个参数同样是基础指标名,后续参数是维度字段。 这些字段必须属于基础指标的数据集,且名称必须带数据集前缀。
| 类型 | 声明要求 | 分组与计算规则 |
|---|---|---|
include |
至少一个维度,外面恰好包一层聚合 | 在展示分组上加入声明维度,先算基础指标,再执行外层聚合 |
exclude |
可以不写维度,声明外面不能包聚合 | 从展示分组中去掉声明维度,重新计算基础指标;不写维度则去掉全部展示分组 |
指标 fixed |
可以不写分组字段,声明外面不能包聚合 | 精确按指定字段计算;不写字段则得到整个计算范围的基准 |
include 的外层聚合支持 SUM、COUNT、AVG、MIN、MAX,外层不接受 DISTINCT。
电商示例的 AVG(include(order_count, orders.user_id)) 先计算各买家的订单数,再求平均。
没有 group_by 时,include 仍先按声明维度计算,再汇总为总体结果。
展示要求的时间粒度会进入它的内层计算。普通过滤和上下文都限定 include 的输入。
exclude 也遵守普通过滤和上下文。它在较粗分组上重新计算,不是相加已有的展示值,
因此去重计数也必须重新统计。带键 exclude 写到的每个字段都必须出现在查询 group_by 中,
时间粒度不限:排除一个查询没有分组的字段什么也排除不掉,结果只会是基础指标本身,所以查询以
lod_dimension_not_grouped 被拒。不带键的 exclude 不要求分组;没有 group_by 时,
就是所选记录上的基础聚合。
指标 fixed 遵守上下文,忽略普通展示过滤。每个固定分组字段必须原样出现在查询 group_by 中,
不能带时间粒度转换,否则查询以 lod_dimension_not_grouped 被拒;无字段的总体基准也可用于无分组查询。
指标目录把带键 exclude、fixed 写到的字段列为 required_dimensions,拒绝时缺的那些列在
missing_dimensions 里。
如果需要把固定分组的结果继续汇总,应改用固定字段加普通聚合,不能在 fixed 指标声明外再包聚合。
同一事实表上的普通指标、exclude、fixed 可以共查,并用 compose 计算比例或其他算术结果。
多个 include 指标共查时,基础数据集、声明维度列表及顺序必须一致;基础指标和外层函数可以不同。
include 不能与其基础指标所读数据集上的普通指标、exclude/fixed 指标或查询实际读取的
LOD 字段共查。
声明写在模型的哪里¶
字段或指标保留普通的 expression.dialects,使用 ANSI_SQL 表达式。
指标 SQL 引用的是已声明的语义字段,名称要带数据集前缀,不能直接引用未声明的物理列。
LOD 扩展放在所属字段或指标的 custom_extensions 中,vendor_name 为 DATUS。
data 是 JSON 编码的字符串。 其中 v 是扩展版本字符串;1.11 支持本页的全部规则。
可选的 requires 列出能力键:固定字段用 lod,派生指标用 derive。
| 定义内容 | JSON 对象中的位置 |
|---|---|
| 固定字段 | lod.expr 写 fixed 声明 |
| LOD 指标 | derive.type 为 lod,derive.expr 写 include、exclude 或 fixed 声明 |
| 带筛选的基础指标 | derive.type 为 filter,derive.base 写基础指标名,derive.where 写条件 |
| 指标间算术组合 | derive.type 为 compose,derive.expr 写使用指标名称的算术表达式 |
下面是电商示例中“买家累计消费”字段的定义,放在 orders 的 fields 列表内。
完整模型还需要定义它引用的 paid_total 指标。
- name: buyer_lifetime_paid
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(orders.paid_amount)
datatype: Decimal
custom_extensions:
- vendor_name: DATUS
data: '{"v":"1.11","is_dimension":false,"lod":{"expr":"fixed(paid_total, orders.user_id)"}}'
LOD 指标放在模型的 metrics 列表内。下面是“渠道内平均每位买家的订单数”,
它引用基础指标 order_count(COUNT(DISTINCT orders.order_id)):
- name: mean_orders
expression:
dialects:
- dialect: ANSI_SQL
expression: AVG(COUNT(DISTINCT orders.order_id))
custom_extensions:
- vendor_name: DATUS
data: '{"v":"1.11","derive":{"type":"lod","expr":"AVG(include(order_count, orders.user_id))"}}'
为什么同时需要 SQL 和 LOD 声明¶
expression 描述计算内容,DATUS 声明说明要按什么粒度分步计算,两者必须一致。
核心 SQL 必须完整展开,不能只写指标名、占位常量或 fixed/include/exclude 声明。
| 定义方式 | 核心 SQL 应写什么 |
|---|---|
| 固定字段 | 基础指标的完整聚合 SQL |
| include 指标 | 用声明中的外层函数包住基础指标的聚合 SQL |
| exclude 或 fixed 指标 | 用 SUM 包住基础指标的聚合 SQL,即使基础指标不是求和 |
| 对固定字段再次聚合的普通指标 | 直接对固定字段引用使用普通聚合函数 |
| compose 指标 | 把表达式中每个指标名替换成该指标的完整核心 SQL |
上述累计消费字段的核心 SQL 是 SUM(orders.paid_amount),对它求用户均值的普通指标是
AVG(orders.buyer_lifetime_paid);上一节的 include 指标写成 AVG(COUNT(DISTINCT orders.order_id))。
exclude 和 fixed 指标的写法最容易让人困惑。下面是电商示例的“当天全站销售额”:
- name: site_amount
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(SUM(orders.paid_amount))
custom_extensions:
- vendor_name: DATUS
data: '{"v":"1.11","derive":{"type":"lod","expr":"fixed(paid_total, orders.paid_date)"}}'
内层 SUM(orders.paid_amount) 是基础指标 paid_total 的 SQL,外层 SUM 是固定的包装,
表示“对基础指标在另一粒度上的结果再取一次”。即使基础指标是 COUNT 或 MAX,外层也写 SUM,
比如以 order_count 为基础的 fixed 指标写成 SUM(COUNT(DISTINCT orders.order_id))。
这个外层 SUM 只用于让 Dosi 核对 SQL 和声明是否一致,不会把基准值累加一遍。
嵌套聚合不能作为普通 SQL 直接执行,Dosi 按扩展声明将它拆成合法的计算步骤。
两份表达不一致时返回 derive_expression_mismatch。
筛选派生的核心 SQL 要展开筛选条件,并代入参数默认值,不保留参数标记。
筛选行数的 COUNT 使用条件表达式:匹配时返回 1,否则返回 NULL,然后计数;
不能仅因语义等价就把这里的 1 换成标识字段。
对值求和或去重计数时,则在匹配时返回被聚合的值,否则返回 NULL,再执行对应聚合。
固定字段重复该筛选聚合 SQL,lod.expr 按名称引用筛选指标。
指标名可以出现在 derive.expr,不能代替核心 SQL。
类型转换和零分母处理,也要在 compose 声明与展开后的核心表达式中保持一致。
计算期间不同:用参数定义独立窗口¶
当固定字段需要自己的计算期间,先定义带筛选的基础指标,把期间写成参数,
再让固定字段引用它。params 与 derive 并列放在基础指标的 DATUS JSON 中,不放在固定字段上。
下面是电商示例里“参考期实付”的两段定义。先是带参数的基础指标,放在 metrics 列表内:
- name: reference_paid_amount
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(CASE WHEN orders.paid_date_key >= 0 AND orders.paid_date_key < 99991231 THEN orders.paid_amount END)
custom_extensions:
- vendor_name: DATUS
data: '{"v":"1.11",
"derive":{"type":"filter","base":"paid_total",
"where":"orders.paid_date_key >= :reference_start AND orders.paid_date_key < :reference_end"},
"params":[{"name":"reference_start","type":"int","default":0,"min":0,"max":99991231},
{"name":"reference_end","type":"int","default":99991231,"min":0,"max":99991231}]}'
再在 users 数据集上定义引用它的固定字段,每个用户一个值:
- name: reference_paid
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(CASE WHEN orders.paid_date_key >= 0 AND orders.paid_date_key < 99991231 THEN orders.paid_amount END)
datatype: Decimal
custom_extensions:
- vendor_name: DATUS
data: '{"v":"1.11","is_dimension":false,"lod":{"expr":"fixed(reference_paid_amount, users.user_id)"}}'
核心 SQL 里的 0 和 99991231 是参数默认值代入后的结果,规则见上一节。
查询时用 --param reference_start=20300401 --param reference_end=20300501 指定 4 月。
每个参数声明 name、type、default。int、float 可设 min/max,
string 可设 allowed;不限定字符串取值时允许开放输入。allowed 与数值上下界不能同时使用。
没有取值列表或数值边界时会产生 datus_param_unbounded 提示,但不会因此使 validate --strict 失败。
已知业务范围时应明确声明。整数范围本身不校验日期编码是否合法,D-PARAM 也没有日期类型。
筛选条件用冒号加参数名引用参数,查询通过 params 或 CLI --param 传值,不自行拼接 SQL。
没有传值时使用默认值。
一个参数值会传给本次查询里所有声明了同名参数的指标,包括查询直接选择的指标,
以及查询读到的固定字段背后的基础指标。所以两段需要分别控制的期间,必须用不同的参数名,
比如电商示例的参考期 reference_start、观察期 observation_start;
共用一个名字,就等于强制两段期间相同。同名参数的值还必须同时满足每个声明的类型和取值范围。
固定字段的一次计算只接受单值,不能绑定列表。
查询无论通过分组、过滤、明细投影,还是通过依赖它的计算字段读取固定字段,参数都会传到它的基础指标。
如果本次查询里没有任何指标声明这个参数名,返回 unknown_metric_param,通常是参数名拼错了;
值的类型错误、超出取值范围,或者给固定字段的参数传了列表,返回 param_out_of_domain。
同表中,展示记录与固定字段观察不同期间时,把展示日期条件放在普通 where_sql,
把字段期间放在参数化基础指标里。查询 time_range 会进入固定计算,导致两段期间相交。
字段自己的条件只能追加约束,不能覆盖 source、时间范围或上下文限制。
需要查询时间范围自动作用于日期字段时,声明原生时间维度或用 D-FORMAT 说明存储格式。普通整数日期码也可以直接与整数参数比较,无须把它声明为时间轴。
跨表计算:先确定结果属于哪张表¶
固定字段可以汇总另一张表的记录。字段定义在哪个数据集,那个数据集就是字段所在表。 它决定哪些记录有资格进入结果;只在被汇总表中出现的对象不会新增结果行。 固定分组字段仍属于字段所在表,每个字段都必须有明确的跨表对应关系。
| 已声明的对应方式 | 被汇总表如何找到分组字段 |
|---|---|
| 两表间直接多对一关系,两个方向均可 | 使用配对键列 |
| 从被汇总表沿多对一路径到达字段所在表 | 沿路径读取对应字段 |
| D-CONFORM 配对 | 使用另一事实表中的配对字段 |
列名相同不代表自动对应。缺少对应、对应冲突或跨表 fixed 没有分组字段,都会被拒绝。
普通关系声明 from、to、from_columns、to_columns,默认多对一。
D-CONFORM 使用相同的列对应列表,并声明 DATUS cardinality: "many_to_many";
它用于结果对应,不把两张事实明细表直接连接。参见 D-CONFORM。
没有匹配记录时,跨表 COUNT 为 0,其他聚合为 NULL。
跨表 NULL 键不匹配任何键,与同表 NULL 分组不同。
SUM 在无记录或全部值为 NULL 时都返回 NULL;业务明确要求零时,通过普通计算字段使用 COALESCE。
查询的时间范围落在被汇总表自己的时间字段上,不管两张表的日期列叫什么、有没有配对;
没有时间字段的表读全部数据,并给出 time_axis_missing 警告。context_filter 按子条件
传播到被汇总表能读取的位置,包括多对一路径或配对列。读不到的子条件跳过,并给出
context_skipped 警告;查询里任何部分都读不到的条件直接拒绝(context_unreadable)。
只能经由存储格式不同的配对列读到的条件返回 not_implemented,这时把期间放进时间范围。
普通 where_sql 仍不会缩小固定计算的输入,所以某次查询要这个字段读全部历史时,
把查询自己的日期写在那里(S-FILTER-2)。
两张事实表各自分类后对齐¶
两张记录业务活动的事实表,可以各自定义固定字段,再用 D-CONFORM 声明共同分类维度。 各自计算字段和指标后,再对齐分组结果。查询可以使用配对维度的任一名称, 只请求另一侧指标时也一样。结果保留两侧分组,缺失 COUNT 默认补 0,SUM 保持 NULL, 除非另外声明填充规则。两边人数相加不表示跨表去重,因为两边可能包含同一对象。
这与“一个固定字段直接汇总另一张表”是不同用法:同时查询两表指标并按后者分组,
会返回 fan_out_risk。普通关系的连接列也不能读取 LOD 值;D-CONFORM 对应不属于这种明细连接。
过滤的详细规则¶
context_filter 不能读取 LOD 值,因为它先限定用于计算 LOD 的记录。
固定字段条件只在固定值产生后生效,不会反过来限定任何固定计算的输入。
已选出的 LOD 指标可以用于结果筛选,执行在计算完成后、排序及 limit 之前;它不能成为分组维度。
未选出的指标用于结果筛选会返回 result_filter_metric_not_selected,
一个结果条件同时引用指标和未分组字段会返回 result_filter_unprojected。
AND 的各子条件分别确定位置。混合原始字段与固定字段的 OR、NOT 或比较表达式, 在固定值可用后整体执行;不能把 OR 拆成多个筛选。 只为展示维度或普通过滤引入的关联影响展示记录,不缩小固定计算的输入,INNER 关联也一样。 需要让匹配记录限定计算时,应把相应条件放进上下文。
时间范围左闭右开。固定分组中的时间键在内部计算时保留原值与存储编码,
再次按固定结果分组时才应用展示时间粒度;include 则在内层细分时应用该粒度。
LOD 字段及依赖它的字段不能声明 dimension.is_time: true。
可以把它们的 datatype 声明为日期,但这不会使它们成为可接收查询时间范围的时间轴。
如何查询已经定义的 LOD¶
指标查询使用 dosi query,选择指标并指定需要的分组。
group_by、where_sql、context_filter、time_range、order_by、limit、params
分别对应 CLI 的 --group-by、--where、--context-filter、--start-time/--end-time、
--order、--limit、--param;指标名称通过 --metrics 提供。
无需在查询里再写一套 LOD 表达式。
明细查询使用 dosi select,通过 --from 指定根数据集,通过 --fields 指定输出字段。
可以读取、筛选、排序根数据集上的固定字段,其基础指标可以来自其他表。
当前不能读取关联数据集上的 LOD 字段或依赖它的计算字段;如果需要的是那张表的记录,应以它为根。
明细查询保留根数据集的记录行数。--distinct 仅去掉重复输出行,不去掉参与 LOD 计算的原始记录。
可以读取沿多对一关系可达的普通维度字段;向多侧遍历会被拒绝,避免记录膨胀。
明细字段的基础指标使用相同的 --param 绑定规则。
能力边界:哪些计算需要拆开¶
限制针对某次查询实际读取的字段和指标,不是禁止它们共存于模型中。 拆分查询时仍要保持相同的业务范围和分母。
下面这些组合可以放在同一次查询里:
| 同一次查询中的组合 | 说明 |
|---|---|
| 原始行指标,固定字段仅用于分组或筛选 | 例如电商示例第 1 题,按一次购买/多次购买分组统计买家数和金额 |
| 对同一组固定分组字段的值再次聚合 | 每个展示组内,每个固定分组只算一次 |
| 多组固定字段只用于展示或筛选 | 其中只有一组可以提供再聚合的值 |
| 同一事实表的普通指标、exclude/fixed 指标及 compose | 例如电商示例第 4 题 |
| 多个 include 指标 | 基础指标读的数据集相同,声明维度的列表和顺序也相同 |
| LOD 指标与别的事实表的指标 | 每张事实表各算一个分支,LOD 在自己那张表的行上、按那张表的筛选和日期计算,结果按分组字段对齐 |
下面这些组合需要换一种写法,或者拆成几次查询。拆分时,每次查询都要用相同的分组、 上下文和时间范围,结果再按分组字段对齐,这样各部分的业务范围和分母才一致。
| 同一次查询中的组合 | 怎么办 |
|---|---|
| 再聚合固定值,同时计算原始行指标 | 拆成两次查询:一次只放再聚合固定值的指标,一次放原始行指标 |
| 再聚合两组不同固定分组字段的值 | 每组固定分组各查一次 |
| include 与其基础指标所读事实表的普通指标、exclude/fixed 指标或 LOD 字段混用 | include 指标单独查询,其余指标另查一次。电商示例第 3 题就是这样处理的 |
| exclude/fixed 指标与查询读取、分组或筛选的 LOD 字段混用 | 拆成两次查询 |
带键 exclude 的字段或 fixed 指标的分组字段没有出现在查询分组中(lod_dimension_not_grouped) |
把这些字段加进 group_by:exclude 的粒度不限,fixed 的要原样加、不带时间粒度。如果要把 fixed 的结果再汇总到更粗的分组,改用固定字段加普通聚合 |
LOD 与窗口指标或 time_ranges |
分开执行;多个期间的对比,每个期间查一次 |
| 指标只是关联到某张表,却按那张表的固定字段分组或筛选 | 改用以那张表为主的指标,或者把固定字段定义在指标自己的数据集上 |
| 基础指标或分组字段间接依赖 LOD,或窗口基础指标使用 LOD | 当前没有替代写法,LOD 不能嵌套 |
| 普通关系的连接列或时间轴使用 LOD 值 | 当前没有替代写法 |
| 对 LOD 指标、条件或维度做归因分析 | 当前不支持。发现接口会把 LOD 指标标为不可归因,LOD 维度可能被跳过并给出提示 |
声明位置错误、基础指标不存在、指标维度没有数据集前缀、对应歧义或非法嵌套,属于建模错误。
不支持的查询组合可能返回 not_implemented、fan_out_risk 或其他具体错误,不能统称为同一错误。
展示维度与另一固定键的输出名称冲突时,返回 duplicate_output_name。
空输入没有分组时返回一行,COUNT 为 0,其他聚合为 NULL;有分组时不产生结果组。 外层 COUNT 统计非 NULL 的中间值,不一定等于原始记录数。LOD 不自动补齐日历或缺失对象。
校验、版本与兼容性¶
先在 datus 模式校验模型,再编译、执行实际查询。 重点核对每个对象的记录数不同时是否仍正确、缺失匹配、过滤位置、日期边界和零分母。 用独立原始 SQL 对照,并改变数据和参数验证计算规则。
dosi validate --osi-datus 检查结构和编译;--strict 还会因字段声明等建模规范警告而失败,
但不把所有编译提示都当成错误。dosi info 可以查看当前运行引擎的扩展能力。
字段应声明真实主键、关系列及维度用途。时间路由要求 dimension.is_time: true。
不推荐作为分析维度的技术字段,在该字段的 DATUS JSON 中设置 is_dimension: false;
true 表示明确推荐。这个设置不禁止查询显式按该字段分组。
仅填写核心 dimension 对象不保证消除所有字段角色提示;标识字段未声明为键或关系列时仍可能出现
underdeclared_field。应明确其实际用途,不能虚构唯一性。固定字段及其派生字段不能声明为时间轴。
通用关系检查也可能对明确声明的事实表对应关系提示目标不唯一,无须为消除提示虚构主键。
Dosi 接受的模型文件结构¶
Dosi 要求根节点包含 version: "0.2.0.dev0",一个文档只放一个模型,有两种写法:
放在只有一个条目的 semantic_model 列表里,条目内是模型的 name、datasets、
relationships、metrics;或者把这些字段直接放在根节点。该引擎不接受 version: "0.1.1"。
上游 0.2.0.dev0 是仍在变化的开发版规范,较新快照把模型移到了根节点,版本字符串却没变。
在上游正式发布这一改动之前,优先用列表写法,0.2.0.dev0 的 schema 校验的是这种写法。参见
一个文档一个模型。
basic 模式不会执行相同的 LOD 计算¶
basic 模式忽略 DATUS 扩展并提示。没有生效 LOD 元数据的聚合字段会被丢弃,
返回 aggregate_field_dropped,后续引用失败。LOD 指标中的嵌套聚合及其组合也会明确失败,
不能依赖 basic 模式得到等价结果。