aloudata logo
产品解决方案客户案例资源中心合作伙伴关于我们立即咨询

Text-to-SQL 没有答错,但答案不一定是你要的那个

作者:Aloudata 团队2026-03-30|NoETL 博客

上一期我们让小龙虾接上了语义层,六轮对话追出了 GMV 下跌的根因,还生成了定时报告。收到反馈最集中的一个疑问是:「我直接让 AI 写 SQL 查数据库不就行了吗?为什么还需要语义层?」这个问题值得认真回答,所以我们做了一组对比实验。这篇文章是实验的完整记录。没时间看视频的话,读这篇就够了。

这篇文章我们会回答四个问题:

一、实验公平吗? —— 我们给了 text-to-SQL 最好的条件。

二、五轮下来到底差多少? —— 一张表说清楚,再逐轮拆解。

三、这些口径是不是你们故意挑的? —— 不是。每条都是真实零售企业里踩过坑之后沉淀下来的共识。

四、那把口径维护在 Skill 或字典里不就行了? —— 方向对了,但还差最后一公里。

一、实验公平吗?

我们用的是一个零售场景的 Demo 数据集:3 张事实表(订单、库存、上市)加 3 张维度表(门店、商品、会员),标准维度建模,总共才 6 张表。现实中的数仓动辄几百张表,字段名经常是一串拼音缩写——跟那种环境比,我们这个已经简单到不能再简单了。

为了让对比尽量公平,我们专门写了一个 text-to-sql-query Skill,把完整的数据库 schema 都编码了进去:字段名、数据类型、中文注释、表间 JOIN 关系,一个不落。我们甚至还告诉它有哪些常见的口径歧义陷阱,要仔细分析和展示查询口径,必要时询问用户。

而且我们问的五个问题都非常基础,全是「上月 XX 是多少」的形式,不涉及归因、预测或任何多步推理,也不用考虑性能优化。就这种难度,来看看两边的答案会不会分叉。

Skill(含完整 schema)都已公开,链接在文末。

二、五轮下来到底差多少?

先上汇总:

轮次 问题 Text-to-SQL 语义层 差距
第一轮 销售额 19,349,217 ✅ 19,349,217 ✅ 0%
第二轮 坪效 30.99 / 6.05(每次不同) 1,527.77(永远一致) 49 ~ 253 倍
第三轮 连带率 58.40 42.39 37.7%
第四轮 净销售额 14,008,435 13,470,801 4.0%
第五轮 复购率 10.56%(促频次) 21.40%(促回访) 一倍 · 运营方向不同

只有第一题的答案完全一致——最简单的 SUM 聚合,没有任何口径歧义。后四题,四种不同的翻车方式。逐轮说。

坪效:同一个问题,问两次答案不一样

坪效就是每平方米产出多少销售额,零售行业最基本的空间效率指标。

语义层坪效的定义是这样:分子是 fact_orders 的销售额求和,分母是 dim_shop 的营业面积求和——但挂了两层过滤。第一层,shop_status = '开店',排除掉已关闭的门店;第二层,分子分母的数据日期都被限制在了查询周期内,只有当月有记录的在营门店才会进入计算。两层过滤叠加之后,2 月份进入分母的只有 24 家门店,面积合计 12,665 平方米。

而 text-to-SQL 这边,我们前后跑了两次,拿到了两个完全不同的结果。第一次是测试,AI 写了个非常直觉的 SQL——销售额除以面积,没做任何过滤,关店的门店面积也算了进去,得到 30.99。第二次录制的时候,AI 主动加上了 shop_status = '开店'。我们一度以为这次会算对呢,结果出来是 6.05——反而偏得更远了。原因是它虽然过滤了门店状态,但没有对 dim_shop 做时间范围过滤,分母变成了全部 6,040 家开店门店的面积总和(320 万平方米),而分子只是上月一个月的销售额。分子和分母的口径完全没有对齐。

「哪些门店该进入分母」以及「分母要不要跟分子对齐时间范围」,这两条规则在 schema 的字段注释里完全找不到。它们是被编码在语义层指标定义里的业务规则,AI 靠读表结构很难准确推断出来。

连带率:毛件数还是净件数

连带率(UPT),指的是每笔交易平均卖出几件商品。text-to-SQL 用的是 retail_quantity,也就是毛销售件数,包含了后来被退掉的部分;语义层用的是 net_quantity,扣除退货之后的净件数。这个月退了将近两万件,所以两个口径差出了 16 件,接近 38%。

哪种更「对」?取决于你是谁。比如销售培训部门关心的是导购当时推了多少件,退货是售后的事,毛件数合理;而商品企划部门关心的是最终留在顾客手里多少件,净件数合理。企业完全可以同时保留毛连带率和净连带率两个指标——但「连带率」这三个字不加限定地出现在月报里的时候,它到底指的是哪一个?这就需要有人来管了。

净销售额:最安静的 4%

数据库里有一个字段就叫 net_amount,字面意思就是「净金额」。AI 看到用户问"净销售额",选了这个字段,完全合情合理。但语义层定义的「净销售额」不是这个字段——它是 retail_amount - return_amount,也就是毛销售额减去退货金额。两者差了 54 万,因为 net_amount 里还包含了一些其他调整项,跟业务团队理解的「净销售额」不是同一个概念。

4% 的偏差是五轮里最小的,但反而最危险。前面坪效差了几十上百倍,连带率差了将近四成——差距大到你一眼就能发现不对。但 4% 放进一张月报表格里,大多数人根本注意不到。54 万就这样安安静静地混了进去,汇报了一整年,年底盘账的时候才发现全年累计差了六百多万。

复购率:同一个词,两种运营方向

text-to-SQL 把「复购」理解成了月内重复购买——当月下过两笔以上订单的客户占比,10.56%。语义层的定义是跨月回访——上个月买过、这个月又来了的客户占比,21.40%。差了整整一倍。

两边给出的建议方向乍看是一致的:都觉得偏低,都建议加大投入。但仔细看就会发现它们指向的运营动作完全不同。10% 对应的策略是「促频次」——怎么让顾客一次多买几单,手段是满减券、凑单优惠;21% 对应的是「促回访」——怎么让上个月的顾客这个月再来,手段是会员召回、到店激励。同样叫「复购率」,如果你带着做好留存的目的来问数,看到 10% 和 20% 你要投入的预算相差的恐怕不止 1 倍了。

三、这些口径是不是你们故意挑的

一定会有人这样想:坪效要过滤门店状态还要对齐时间、连带率要用净件数、复购率用跨月口径——这些看起来那么「讲究」的定义,是不是你们为了衬托语义层刻意设计的?

不是。这些就是真实零售企业在经营过程中,被各种数据事故教训出来的规则。坪效的分母不过滤关店门店,管理层看到的空间效率指标就是失真的,据此做出的门店调整方案会全部偏离;连带率混用毛净口径,退货率高的月份里销售团队可能反而以为自己干得不错;复购率的定义运营和会员两个团队各用一套,季度复盘的时候如果两个口径都上了总经理办公会,信任就崩了。

每一条规则背后都是踩过的坑。如果你觉得这些口径「刁钻」,恰恰说明这类业务常识在你的组织里可能还是隐性的、靠口头传递的——而口头传递到不了 AI 那里。

四、那把口径维护在 Skill 或字典里不就行了

这个思路的方向是对的——你已经看到了核心问题不在 AI 的能力,而在口径的管理。

具体做法无非两种。一种是把指标定义直接写进 Skill 的 prompt 里,告诉 AI「遇到坪效要怎么过滤、复购率用跨月口径」。另一种更优雅一点,维护一份口径字典,AI 每次查数之前先去字典里检索对应定义,再据此生成 SQL。

两种都试得通,但都绕不开同一个问题:AI 拿到了正确的定义之后,还是要自己把它翻译成 SQL。翻译这一步,就可能漏。

坪效那一轮已经说明了问题。就算你把定义写得清清楚楚——分母只取在营门店、时间范围要跟分子对齐——AI 第二次确实做到了过滤门店状态,但维度表的时间过滤还是漏掉了。两层规则只落地了一层,结果偏得比不过滤的时候还远。

还有一个更现实的问题:规模。5 个指标的定义塞进 prompt 或字典没有任何压力,但真实企业动辄几百上千个指标。全塞进 prompt,模型的注意力会断崖式下降;放在字典里检索好一些,但指标口径不是定好了就一成不变的——下个季度「坪效」的分母可能从「在营门店」改成「在营满 30 天的门店」,你得在字典里持续维护,对它负责,AI 则要找到它、改对它,然后祈祷没有遗漏。

语义层的做法则是定义即执行。你在语义层里定义好坪效的口径,查询时这个定义直接生成查询结果,中间没有「AI 读懂定义→AI 自己再写一遍 SQL」这个翻译环节。没有翻译,就没有遗漏的机会。

打个比方:把口径写进 Skill 是用记事本管配置,维护口径字典是用 Excel 管配置,语义层是用配置中心管配置。思路一脉相承,但能承载的复杂度完全不在一个量级。

最后说几句

这次实验最打动我们的发现,其实不是「text-to-SQL 容易出错」——它给出的每一个数字都是数据库里真真切切算出来的,没有一个是「错」的。真正的问题在于:同一个业务概念,每次问都可能得到不同的答案。

在 BI 时代,口径不一致的问题当然也存在,但它有一个天然的纠偏机制:数据是人生产的,也是人消费的。分析师出了一版报表,业务负责人看完觉得不对,开个会对一下口径,下次就改过来了。口径的对齐发生在人与人的沟通中——虽然低效,但总归有人兜底。

到了 AI 时代,这个纠偏环节消失了。AI 写完 SQL 直接返回结果,没有人在中间「看一眼觉得不对劲」,甚至未来的消费者都不再是人类。如果口径本身没有被显性地定义和管理,AI 每次都是在临场发挥——后果会非常严重。

与此同时,业务本身是流动的。口径不能只沉淀不变更,管理和生产必须是动态一致的。这两点加在一起——AI 时代需要显性的语义治理,而语义本身又在持续演化——决定了你需要的不是一份静态的文档或字典,而是一个活的系统。

Aloudata CAN 就是这样一个系统。它不只是管定义的:定义指标时强制进行口径判重和名称去重,让同一个概念不可能同时存在两套互相矛盾的口径;强制注册属性信息,每个指标的计算逻辑、负责人、适用范围都有据可查。更关键的是,它同时也是一个动态数据服务引擎——内置智能加速引擎,代持了传统 DWS/ADS 层的人工 ETL 工程。你不需要手工建宽表,定义好指标,Aloudata CAN 自动完成从管理到查询的全链路。

一句话总结:语义层不是 AI 的替代品,是 AI 的前置依赖。

资源

https://clawhub.ai/jackyujun/metric-query

https://clawhub.ai/jackyujun/metric-attribution

  • 申请 Aloudata CAN Demo 环境 API Key:

申请 Aloudata CAN Demo 环境 API Key

下一篇
从 OpenClaw 到企业 Agent:为什么真正的门槛在语义层
联系我们
contact us code
扫码关注 Aloudata 微信公众号
获取更多 NoETL 技术干货
contact us code
扫码加入 Aloudata 技术交流群
获取更多最新案例资讯

即刻开启可信智能之旅

我们的行业专家会第一时间联系您,帮助您了解更多