答案构建器(Answer Builder)最佳实践

答案构建器(Answer Builder)是 Analytics Agent 语义层里的"复杂指标(complex_metric)"——你写一段带参数占位符的 SQL 分析模板,系统把它变成一个可交互、可复用的分析资产:终端用户在提问时可以切换维度、勾选筛选条件,得到结构化的多列结果。

它和普通指标(simple_metric,即

metric
metric
)互补:

普通指标
metric
metric
答案构建器
answer-builder
answer-builder
本质单表 + 单个聚合表达式参数化的复杂分析 SQL 模板
能表达
SUM(amount)
SUM(amount)
COUNT(*)
COUNT(*)
这类单一口径
多派生比率、排名/占比、跨表关联、时序对比、多维小计
交互
${dims}
${dims}
切维度、
${filters}
${filters}
加筛选
输出单个数值多列结果,每列一个命名指标

一句话选型:能用一个聚合表达式说清楚的,用

metric
metric
;需要多步计算、窗口、跨表、时序对比、可交互下钻的,用
answer-builder
answer-builder

什么时候需要答案构建器

以下分析普通指标做不到,必须用答案构建器:

  • 多个相互关联的派生比率:客单价、折扣占比、新客占比要在同一张结果里一起算
  • 排名与累计占比:帕累托分析(Top 产品贡献了多少销售额),需要窗口函数
  • 跨表关联分析:卖得多的产品售后满意度如何——销售表关联售后表
  • 时序对比:月度环比增长,需要
    LAG
    LAG
    引用上一行
  • 多维小计:分区域分产品的销售额 + 各级汇总一次出(
    ROLLUP
    ROLLUP
  • 可交互分析:同一个模板,用户运行时自选维度、自定筛选条件

涉及的命令

以下命令均以

cz-cli analytics-agent
cz-cli analytics-agent
为前缀(例如
cz-cli analytics-agent answer-builder validate ...
cz-cli analytics-agent answer-builder validate ...
):

命令用途适用场景
answer-builder validate
answer-builder validate
校验 DSL(dry-run,不落库)创建前先验证语法和配置
answer-builder create
answer-builder create
创建答案构建器校验通过后落库
answer-builder list
answer-builder list
列出某个域的答案构建器查看已有资产
answer-builder detail <id>
answer-builder detail <id>
查看完整定义复制现有的作模板改
answer-builder update <id>
answer-builder update <id>
更新定义改 SQL / 维度 / 指标名
answer-builder enable/disable <id>
answer-builder enable/disable <id>
启用/停用上下线管理

DSL 结构(
--content
--content

答案构建器的核心是一段 DSL JSON(通过

--content
--content
传入),包含四个顶层字段:

{ "chartParams": [ // 交互输入参数,SQL 里用 ${name} 引用 {"name":"dims","type":"dimension","allowMulti":true, // -> GROUP BY ${dims} "fromTableRefs":[{"tableName":"cat.schema.table","columns":["region"]}]}, {"name":"filters","type":"filter","allowMulti":true, // -> WHERE ${filters} "fromTableRefs":[{"tableName":"cat.schema.table","columns":["channel"]}]} ], "outputColumns": [ // 每个 SELECT 输出列对应一项 {"name":"total_amount", // 必须与 SQL 的 AS 别名一致 "metricName":"区域销售额", // 必填,且在域内唯一 "type":"decimal","stdTypeName":"double", // type 必填,stdTypeName 可选 "alias":["销售额"], // 可选,展示别名 "description":"按区域汇总的销售总额"} // 可选 ], "relatedTables": ["cat.schema.table"], // SQL 涉及的所有表 "sql": "SELECT ${dims}, SUM(final_amount) AS total_amount FROM ... GROUP BY ${dims}" }

字段说明

字段作用关键点
chartParams[].name
chartParams[].name
占位符名,SQL 里写
${name}
${name}
每个 SQL 占位符必须在此有对应项
chartParams[].type
chartParams[].type
dimension
dimension
(分组维度)/
filter
filter
(筛选条件)
dimension → GROUP BY;filter → WHERE
chartParams[].allowMulti
chartParams[].allowMulti
是否允许多选维度多选可下钻,筛选多选可组合
chartParams[].fromTableRefs
chartParams[].fromTableRefs
该参数可选的表和列用户交互时从这些列里选
outputColumns[].name
outputColumns[].name
输出列名必须等于 SQL 里的
AS
AS
别名
outputColumns[].metricName
outputColumns[].metricName
指标名(页面显示)必填,且在域内唯一
outputColumns[].type
outputColumns[].type
数据类型(
bigint
bigint
/
decimal
decimal
…)
必填
outputColumns[].alias
outputColumns[].alias
展示别名(数组)可选
outputColumns[].description
outputColumns[].description
指标描述可选
relatedTables
relatedTables
SQL 涉及的所有表JOIN 时把维表也列进去
sql
sql
分析 SQL 模板建议用
--sql
--sql
单独传,避免引号转义

--sql
--sql
分离 SQL

SQL 里常有单引号(

WHERE status='已完成'
WHERE status='已完成'
),塞进
--content
--content
JSON 要层层转义、极易出错。用独立的
--sql
--sql
参数传 SQL,CLI 会自动把它注入 content 的
sql
sql
字段。
--content
--content
--sql
--sql
至少提供其一。

五条必记规则

这五条是实操中最容易踩坑、也最影响成败的规则。

1. 每个
${name}
${name}
占位符必须在 chartParams 中有对应项

SQL 里写了

${dims}
${dims}
,chartParams 里就必须有一个
name:"dims"
name:"dims"
的项。否则占位符不会被替换,
$
$
裸留在 SQL 里,报错:

CZLH-42000: Syntax error at or near '$'

2.
outputColumns[].metricName
outputColumns[].metricName
必填,且在域内唯一

每个输出列都要有

metricName
metricName
(页面上的"指标名")。缺失会导致页面显示"请输入指标名"、无法保存;在同一个域内重名会报错:

CZD-99999: 答案构建器输出指标名【销售总额】和域中的指标名重名

3. 窗口函数 / ROLLUP 引用
${dims}
${dims}
列时,用子查询包裹

RANK() OVER (PARTITION BY ...)
RANK() OVER (PARTITION BY ...)
LAG(...) OVER (ORDER BY ...)
LAG(...) OVER (ORDER BY ...)
ROLLUP(${dims})
ROLLUP(${dims})
里的列正好是
${dims}
${dims}
展开出来的列时,占位符替换会与窗口/分组的列引用冲突,报语义错误。

规避方法:内层子查询用固定列名完成窗口/聚合计算,外层再

SELECT ${dims}
SELECT ${dims}
选取

-- ❌ 直接在窗口里用 ${dims} 展开的列,冲突报错 SELECT ${dims}, RANK() OVER (PARTITION BY region ORDER BY SUM(final_amount) DESC) AS rk FROM t GROUP BY ${dims} -- ✅ 内层固定列名算好,外层只选取 SELECT ${dims}, amt, rank_in_region FROM ( SELECT region, channel, SUM(final_amount) AS amt, RANK() OVER (PARTITION BY region ORDER BY SUM(final_amount) DESC) AS rank_in_region FROM t GROUP BY region, channel ) x

4.
outputColumns[].name
outputColumns[].name
必须等于 SQL 的
AS
AS
别名

输出列靠

name
name
和 SQL 的
AS
AS
别名对齐。两者不一致时,前端拿不到对应的值。列名可以直接用中文(用反引号包裹):
SUM(final_amount) AS \
SUM(final_amount) AS \
销售总额``。

5. 先
validate
validate
create
create

validate
validate
是 dry-run,不落库,返回
valid
valid
/
errors
errors
/
warnings
warnings
。它会检查名称、配置、域表三方面,能在创建前抓出占位符缺失、SQL 语法、指标名重复等问题。养成"先校验后创建"的习惯,避免产出错误资产。

前置准备

本文所有示例基于一个 ICT 销售与售后服务分析域,包含以下表(

quick_start.ict_industry_demo
quick_start.ict_industry_demo
下):

说明关键列
v_gpt_fact_sales
v_gpt_fact_sales
销售订单事实表sale_id, order_no, region, channel, product_type, salesperson, quantity, final_amount, sale_date, customer_id, product_id
v_gpt_fact_service
v_gpt_fact_service
售后服务工单表service_id, order_no, service_type, status, satisfaction_score, response_days, cost, customer_id, product_id
v_gpt_dim_customer
v_gpt_dim_customer
客户维表customer_id, industry, customer_level, region
v_gpt_dim_product
v_gpt_dim_product
产品维表product_id, brand_vendor, category, product_type
v_gpt_ads_monthly_sales_summary
v_gpt_ads_monthly_sales_summary
月度销售汇总stat_month, region, channel, product_type, order_count, final_amount, discount_amount, original_amount, customer_count, new_customer_count

域已配置好维表到事实表的 JOIN 关系(客户/产品 → 销售/售后)。

以下每个场景都给出完整的

create
create
命令,并已通过
validate
validate
语法校验。示例统一用
--domain-id 43 --datasource-id 8448
--domain-id 43 --datasource-id 8448
(请替换为你自己的域和数据源 ID)。

场景一:单维度聚合(入门)

业务问题:各区域的订单数和销售总额。

cz-cli analytics-agent answer-builder create \ --domain-id 43 --datasource-id 8448 \ --analysis-name "各区域销售汇总" \ --content '{"chartParams":[{"name":"dims","type":"dimension","allowMulti":true,"fromTableRefs":[{"tableName":"quick_start.ict_industry_demo.v_gpt_fact_sales","columns":["region"]}]}],"outputColumns":[{"name":"order_count","metricName":"区域订单数","type":"bigint","stdTypeName":"int"},{"name":"total_amount","metricName":"区域销售额","type":"decimal","stdTypeName":"double"}],"relatedTables":["quick_start.ict_industry_demo.v_gpt_fact_sales"]}' \ --sql "SELECT \${dims}, COUNT(*) AS order_count, SUM(final_amount) AS total_amount FROM quick_start.ict_industry_demo.v_gpt_fact_sales GROUP BY \${dims}"

其中

--sql
--sql
的 SQL 格式化后:

SELECT ${dims}, COUNT(*) AS order_count, SUM(final_amount) AS total_amount FROM quick_start.ict_industry_demo.v_gpt_fact_sales GROUP BY ${dims}

要点

dims
dims
维度多选(
allowMulti:true
allowMulti:true
),用户运行时可切换成按 channel、product_type 等下钻;两个输出列都带了唯一的中文
metricName
metricName

场景二:带筛选参数 + 中文指标名(推荐范式)

业务问题:按销售员看业绩,运行时可按区域/渠道/产品类型任意筛选。

cz-cli analytics-agent answer-builder create \ --domain-id 43 --datasource-id 8448 \ --analysis-name "销售员业绩(可筛选区域渠道产品)" \ --content '{"chartParams":[{"name":"filters","type":"filter","allowMulti":true,"fromTableRefs":[{"tableName":"quick_start.ict_industry_demo.v_gpt_fact_sales","columns":["region","channel","product_type"]}]},{"name":"dims","type":"dimension","allowMulti":true,"fromTableRefs":[{"tableName":"quick_start.ict_industry_demo.v_gpt_fact_sales","columns":["salesperson"]}]}],"outputColumns":[{"name":"订单数","metricName":"销售员订单数","type":"bigint","stdTypeName":"int"},{"name":"销售总额","metricName":"销售员销售总额","type":"decimal","stdTypeName":"double"},{"name":"平均客单价","metricName":"销售员客单价","type":"decimal","stdTypeName":"double"}],"relatedTables":["quick_start.ict_industry_demo.v_gpt_fact_sales"]}' \ --sql "SELECT \${dims}, COUNT(*) AS \`订单数\`, SUM(final_amount) AS \`销售总额\`, ROUND(AVG(final_amount),2) AS \`平均客单价\` FROM quick_start.ict_industry_demo.v_gpt_fact_sales WHERE \${filters} GROUP BY \${dims}"

其中

--sql
--sql
的 SQL 格式化后:

SELECT ${dims}, COUNT(*) AS `订单数`, SUM(final_amount) AS `销售总额`, ROUND(AVG(final_amount), 2) AS `平均客单价` FROM quick_start.ict_industry_demo.v_gpt_fact_sales WHERE ${filters} GROUP BY ${dims}

要点

filters
filters
列了三个可筛选列,SQL 用
WHERE ${filters}
WHERE ${filters}
,用户运行时勾选筛选值;输出列的 SQL
AS
AS
别名和
outputColumns[].name
outputColumns[].name
都用了中文,且
metricName
metricName
加了"销售员"前缀保证域内唯一。

场景三:跨表 JOIN 关联分析

业务问题:卖得多的产品,售后满意度和工单率如何?——销售表关联售后表,普通指标只能单表,做不到。

cz-cli analytics-agent answer-builder create \ --domain-id 43 --datasource-id 8448 \ --analysis-name "产品销售与售后质量关联" \ --content '{"chartParams":[{"name":"dims","type":"dimension","allowMulti":true,"fromTableRefs":[{"tableName":"quick_start.ict_industry_demo.v_gpt_fact_sales","columns":["product_type"]}]}],"outputColumns":[{"name":"sales_amount","metricName":"产品销售额(关联售后)","type":"decimal","stdTypeName":"double"},{"name":"service_count","metricName":"产品售后工单数","type":"bigint","stdTypeName":"int"},{"name":"avg_satisfaction","metricName":"产品售后满意度","type":"decimal","stdTypeName":"double"},{"name":"service_per_order","metricName":"产品单均工单数","type":"decimal","stdTypeName":"double"}],"relatedTables":["quick_start.ict_industry_demo.v_gpt_fact_sales","quick_start.ict_industry_demo.v_gpt_fact_service"]}' \ --sql "SELECT \${dims}, SUM(s.final_amount) AS sales_amount, COUNT(DISTINCT sv.service_id) AS service_count, ROUND(AVG(sv.satisfaction_score),2) AS avg_satisfaction, ROUND(COUNT(DISTINCT sv.service_id)*1.0/COUNT(DISTINCT s.sale_id),3) AS service_per_order FROM quick_start.ict_industry_demo.v_gpt_fact_sales s LEFT JOIN quick_start.ict_industry_demo.v_gpt_fact_service sv ON s.order_no=sv.order_no GROUP BY \${dims}"

其中

--sql
--sql
的 SQL 格式化后:

SELECT ${dims}, SUM(s.final_amount) AS sales_amount, COUNT(DISTINCT sv.service_id) AS service_count, ROUND(AVG(sv.satisfaction_score), 2) AS avg_satisfaction, ROUND(COUNT(DISTINCT sv.service_id) * 1.0 / COUNT(DISTINCT s.sale_id), 3) AS service_per_order FROM quick_start.ict_industry_demo.v_gpt_fact_sales s LEFT JOIN quick_start.ict_industry_demo.v_gpt_fact_service sv ON s.order_no = sv.order_no GROUP BY ${dims}

要点

relatedTables
relatedTables
把销售表和售后表都列进去;用
LEFT JOIN
LEFT JOIN
保证没售后记录的产品也出现(销售额在、工单数为 0)。

场景四:窗口函数——排名与累计占比(帕累托分析)

业务问题:哪些产品类型贡献了大部分销售额?(Top 产品的累计占比)。需要窗口函数,普通指标无此能力。

cz-cli analytics-agent answer-builder create \ --domain-id 43 --datasource-id 8448 \ --analysis-name "产品销售排名与累计占比(帕累托)" \ --content '{"chartParams":[{"name":"dims","type":"dimension","allowMulti":true,"fromTableRefs":[{"tableName":"quick_start.ict_industry_demo.v_gpt_fact_sales","columns":["product_type"]}]}],"outputColumns":[{"name":"total_amount","metricName":"产品销售额(帕累托)","type":"decimal","stdTypeName":"double"},{"name":"sales_rank","metricName":"产品销售排名","type":"bigint","stdTypeName":"int"},{"name":"cum_ratio","metricName":"产品累计占比","type":"decimal","stdTypeName":"double"}],"relatedTables":["quick_start.ict_industry_demo.v_gpt_fact_sales"]}' \ --sql "SELECT \${dims}, SUM(final_amount) AS total_amount, RANK() OVER (ORDER BY SUM(final_amount) DESC) AS sales_rank, ROUND(SUM(SUM(final_amount)) OVER (ORDER BY SUM(final_amount) DESC)*100.0/SUM(SUM(final_amount)) OVER (),2) AS cum_ratio FROM quick_start.ict_industry_demo.v_gpt_fact_sales GROUP BY \${dims}"

其中

--sql
--sql
的 SQL 格式化后:

SELECT ${dims}, SUM(final_amount) AS total_amount, RANK() OVER (ORDER BY SUM(final_amount) DESC) AS sales_rank, ROUND(SUM(SUM(final_amount)) OVER (ORDER BY SUM(final_amount) DESC) * 100.0 / SUM(SUM(final_amount)) OVER (), 2) AS cum_ratio FROM quick_start.ict_industry_demo.v_gpt_fact_sales GROUP BY ${dims}

要点

RANK()
RANK()
排名、
SUM(...) OVER (ORDER BY ...)
SUM(...) OVER (ORDER BY ...)
算累计。这里
${dims}
${dims}
在最外层 SELECT,没进 PARTITION BY,所以不触发规则 3 的冲突。

场景五:时序环比——区域内渠道排名要用子查询包裹

业务问题:每个区域内,各销售渠道的销售额排名。这里

RANK() OVER (PARTITION BY region ...)
RANK() OVER (PARTITION BY region ...)
region
region
正是
${dims}
${dims}
展开列,直接写会冲突,必须按规则 3 用子查询包裹。

cz-cli analytics-agent answer-builder create \ --domain-id 43 --datasource-id 8448 \ --analysis-name "区域渠道效能矩阵" \ --content '{"chartParams":[{"name":"dims","type":"dimension","allowMulti":true,"fromTableRefs":[{"tableName":"quick_start.ict_industry_demo.v_gpt_ads_monthly_sales_summary","columns":["region","channel"]}]}],"outputColumns":[{"name":"amt","metricName":"区域渠道销售额","type":"decimal","stdTypeName":"double"},{"name":"rank_in_region","metricName":"渠道区域内排名","type":"bigint","stdTypeName":"int"}],"relatedTables":["quick_start.ict_industry_demo.v_gpt_ads_monthly_sales_summary"]}' \ --sql "SELECT \${dims}, amt, rank_in_region FROM (SELECT region, channel, SUM(final_amount) AS amt, RANK() OVER (PARTITION BY region ORDER BY SUM(final_amount) DESC) AS rank_in_region FROM quick_start.ict_industry_demo.v_gpt_ads_monthly_sales_summary GROUP BY region, channel) t"

其中

--sql
--sql
的 SQL 格式化后(注意内外两层结构):

SELECT ${dims}, amt, rank_in_region FROM ( SELECT region, channel, SUM(final_amount) AS amt, RANK() OVER (PARTITION BY region ORDER BY SUM(final_amount) DESC) AS rank_in_region FROM quick_start.ict_industry_demo.v_gpt_ads_monthly_sales_summary GROUP BY region, channel ) t

要点:内层子查询用固定列名

region, channel
region, channel
完成 PARTITION BY 排名,外层
SELECT ${dims}
SELECT ${dims}
只做选取——这是窗口/时序类分析的通用范式。

场景六:多维小计(ROLLUP)与风险标记(条件聚合 + 子查询)

多维小计——分区域分产品的销售额 + 各级汇总一次出:

cz-cli analytics-agent answer-builder create \ --domain-id 43 --datasource-id 8448 \ --analysis-name "销售额多维小计报表" \ --content '{"chartParams":[{"name":"dims","type":"dimension","allowMulti":true,"fromTableRefs":[{"tableName":"quick_start.ict_industry_demo.v_gpt_fact_sales","columns":["region","product_type"]}]}],"outputColumns":[{"name":"total_amount","metricName":"多维小计销售额","type":"decimal","stdTypeName":"double"},{"name":"order_cnt","metricName":"多维小计订单数","type":"bigint","stdTypeName":"int"}],"relatedTables":["quick_start.ict_industry_demo.v_gpt_fact_sales"]}' \ --sql "SELECT \${dims}, SUM(final_amount) AS total_amount, COUNT(*) AS order_cnt FROM quick_start.ict_industry_demo.v_gpt_fact_sales GROUP BY ROLLUP(\${dims})"

其中

--sql
--sql
的 SQL 格式化后:

SELECT ${dims}, SUM(final_amount) AS total_amount, COUNT(*) AS order_cnt FROM quick_start.ict_industry_demo.v_gpt_fact_sales GROUP BY ROLLUP(${dims})

风险象限——标记"高销量但低满意度"的高风险产品,用

CASE WHEN
CASE WHEN
+ 相关子查询算全局阈值:

cz-cli analytics-agent answer-builder create \ --domain-id 43 --datasource-id 8448 \ --analysis-name "产品口碑风险预警象限" \ --content '{"chartParams":[{"name":"dims","type":"dimension","allowMulti":true,"fromTableRefs":[{"tableName":"quick_start.ict_industry_demo.v_gpt_dim_product","columns":["brand_vendor","category"]}]}],"outputColumns":[{"name":"sales_amt","metricName":"品牌销售额","type":"decimal","stdTypeName":"double"},{"name":"avg_sat","metricName":"品牌满意度","type":"decimal","stdTypeName":"double"},{"name":"complaint_rate","metricName":"品牌工单率","type":"decimal","stdTypeName":"double"},{"name":"risk_flag","metricName":"品牌口碑风险标记","type":"bigint","stdTypeName":"int"}],"relatedTables":["quick_start.ict_industry_demo.v_gpt_fact_sales","quick_start.ict_industry_demo.v_gpt_fact_service","quick_start.ict_industry_demo.v_gpt_dim_product"]}' \ --sql "SELECT \${dims}, SUM(s.final_amount) AS sales_amt, ROUND(AVG(sv.satisfaction_score),2) AS avg_sat, ROUND(COUNT(DISTINCT sv.service_id)*100.0/COUNT(DISTINCT s.sale_id),2) AS complaint_rate, CASE WHEN AVG(sv.satisfaction_score)<3 AND SUM(s.final_amount)>(SELECT AVG(final_amount) FROM quick_start.ict_industry_demo.v_gpt_fact_sales) THEN 1 ELSE 0 END AS risk_flag FROM quick_start.ict_industry_demo.v_gpt_fact_sales s JOIN quick_start.ict_industry_demo.v_gpt_dim_product p ON s.product_id=p.product_id LEFT JOIN quick_start.ict_industry_demo.v_gpt_fact_service sv ON s.order_no=sv.order_no GROUP BY \${dims}"

其中

--sql
--sql
的 SQL 格式化后:

SELECT ${dims}, SUM(s.final_amount) AS sales_amt, ROUND(AVG(sv.satisfaction_score), 2) AS avg_sat, ROUND(COUNT(DISTINCT sv.service_id) * 100.0 / COUNT(DISTINCT s.sale_id), 2) AS complaint_rate, CASE WHEN AVG(sv.satisfaction_score) < 3 AND SUM(s.final_amount) > (SELECT AVG(final_amount) FROM quick_start.ict_industry_demo.v_gpt_fact_sales) THEN 1 ELSE 0 END AS risk_flag FROM quick_start.ict_industry_demo.v_gpt_fact_sales s JOIN quick_start.ict_industry_demo.v_gpt_dim_product p ON s.product_id = p.product_id LEFT JOIN quick_start.ict_industry_demo.v_gpt_fact_service sv ON s.order_no = sv.order_no GROUP BY ${dims}

要点

risk_flag
risk_flag
CASE WHEN 满意度<3 AND 销售额>全局均值 THEN 1 ELSE 0
CASE WHEN 满意度<3 AND 销售额>全局均值 THEN 1 ELSE 0
把复杂判断沉淀成一个可直接筛选的标记列——这类"业务规则内嵌"正是答案构建器相比普通指标的核心价值。

SQL 能力边界

以下高级 SQL 特性均已通过

validate
validate
语法校验确认支持,答案构建器几乎能表达任意分析型 SQL:

特性支持典型用途
条件聚合
CASE WHEN
CASE WHEN
占比、风险标记
窗口函数
RANK/SUM OVER
RANK/SUM OVER
排名、累计、帕累托
PARTITION BY
PARTITION BY
分组窗口
✅(需子查询包裹)组内排名
LAG/LEAD
LAG/LEAD
时序
✅(需子查询包裹)环比、同比
CTE(
WITH
WITH
多步计算
多表 JOIN(含 4 表)跨主题关联
相关子查询对全局/父集算占比
ROLLUP
ROLLUP
/
GROUPING SETS
GROUPING SETS
多维小计
NTILE
NTILE
分桶
分层、分位
PERCENTILE
PERCENTILE
百分位
中位数、分位数
HAVING
HAVING
聚合后过滤

常见错误对照

报错原因解决
CZLH-42000: Syntax error at or near ','
CZLH-42000: Syntax error at or near ','
--sql
--sql
用双引号且未转义,
${dims}
${dims}
/
${filters}
${filters}
被 shell 展开成空串,变成
SELECT ,
SELECT ,
--sql
--sql
改用单引号,或在双引号内把
$
$
转义为
\$
\$
(见「用
--sql
--sql
分离 SQL」的 shell 引号陷阱)
CZLH-42000: Syntax error at or near '$'
CZLH-42000: Syntax error at or near '$'
SQL 里的
${name}
${name}
在 chartParams 无对应项
补上对应的 chartParams 项(规则 1)
CZLH-42000: Semantic analysis exception
CZLH-42000: Semantic analysis exception
窗口/ROLLUP 引用了
${dims}
${dims}
展开的列
用子查询包裹(规则 3)
CZD-99999: 输出指标名【X】重名
CZD-99999: 输出指标名【X】重名
metricName
metricName
在域内重复
加业务上下文前缀,保证域内唯一(规则 2)
页面显示"请输入指标名"
outputColumns
outputColumns
metricName
metricName
每个输出列补上
metricName
metricName
(规则 2)

推荐工作流

  1. 确认必要性:这个分析用普通指标(
    metric
    metric
    )能表达吗?能就用 metric;不能(多派生比率/窗口/跨表/时序/交互)再用答案构建器。
  2. 复用模板
    answer-builder detail <已有id>
    answer-builder detail <已有id>
    导出一个相近的定义,照着改,比从零写快且不易错。
  3. 先校验
    answer-builder validate ...
    answer-builder validate ...
    dry-run,确认
    valid:true
    valid:true
    errors:[]
    errors:[]
  4. 再创建
    answer-builder create ...
    answer-builder create ...
  5. 核对指标名:确认每个输出列的
    metricName
    metricName
    已填且域内唯一。

相关文档

联系我们
预约咨询
微信咨询
电话咨询
邮件咨询