面试官可能会问:“数据库里有上百张表,用户只说‘查上个月华东的活跃客户’,你怎么让模型知道该用哪些表和字段?”
很多 Text2SQL Demo 会把全部建表语句塞进 Prompt,让模型直接生成 SQL。表少时看起来能跑,表一多就会出现三类问题:上下文被无关字段占满;同名字段和相似表互相干扰;用户说的是业务词,数据库里却只有技术字段。
更难的是“活跃客户”本身没有唯一含义。它可能指登录过、下过单、产生过付费或满足某个客户分层规则。“上个月”按自然月还是最近三十天,“华东”按客户注册地、收货地还是组织归属,也都需要业务定义。
所以高质量 Text2SQL 要先把问题拆成指标、维度、时间、粒度、过滤条件和业务实体,再从元数据中选择最小但完整的 Schema,之后才轮到 SQL 生成。选不清时要提出最小澄清问题,不能用模型猜测掩盖歧义。
先给出 30 秒回答
面对大 Schema,我不会把所有 DDL 直接塞给模型。先把用户问题解析成业务指标、维度、时间范围、统计粒度、过滤条件和实体,再通过业务术语词典、表列描述、主外键关系、示例值和权限生成候选表列。候选召回后要补齐 Join 路径,形成最小可执行 Schema,再让模型做字段映射。若“活跃客户”“收入”“上个月”存在多个合法定义,系统应比较候选解释和置信证据,提出一个能最大化消除歧义的澄清问题。评估要分别看表召回、列映射、Join 路径、澄清决策和最终 SQL,不能只看执行成功。
核心原则是:先缩小问题空间并确认业务语义,再生成 SQL。

业务解析、Schema 召回、关系补全和歧义澄清发生在 SQL 生成之前。
为什么全量 Schema 会让模型变差
全量 DDL 不只是消耗 Token。真正的问题是它把大量相似候选放在模型面前,却没有说明业务含义和权威关系。
一个系统里可能同时有订单主表、订单明细、支付流水、退款记录、离线宽表和历史快照。它们都包含金额和时间字段。模型看到 amount、total_amount、pay_amount、gmv 时,并不知道哪个是下单金额、实付金额、退款前金额或已经聚合的口径。
表越多,同名列越常见。created_at 可能是客户注册时间、订单创建时间或记录同步时间。只靠列名相似度,系统很容易选到“看起来像”的字段。
全量上下文还会稀释关系信息。模型可能找到了事实表和维表,却不知道应该经过哪张桥接表,或者错误地把两个非唯一键直接连接,导致结果重复。
因此 Schema 裁剪不是简单节省上下文,而是把模型的选择空间限制在业务上合理、权限上可用、关系上连通的子图里。
元数据字典要补足 DDL 没说的内容
DDL 通常只有表名、列名、类型和约束,业务问题需要更多信息。
表级元数据可以包含业务描述、数据域、负责人、更新频率、数据新鲜度、主键、分区键、常见查询场景和访问等级。列级元数据可以包含业务含义、单位、枚举说明、是否可空、示例值、敏感等级、聚合方式和有效时间语义。
指标还需要单独的语义定义。例如“支付金额”对应哪个事实字段,是否扣除退款,按支付成功时间还是订单完成时间,统计粒度是什么。把这些口径只写在 Prompt 里很难维护,应该放在可版本化的指标或业务术语层。
示例值能帮助实体映射。用户说“华东”,数据库可能保存地区编码;用户说某个产品简称,维表里可能是标准名称。示例值只能提供候选,不能把敏感列的真实数据大规模暴露给模型。
元数据要记录来源和版本。表结构变化、口径更新后,旧说明不能继续参与生成。没有版本的 Schema 缓存会让系统在数据库已经变更后仍生成旧字段。
先把自然语言问题拆成六个槽位
一个可操作的解析结果通常包括:指标、维度、时间、粒度、过滤和实体。
“查上个月华东的活跃客户”里,指标可能是活跃客户数或活跃客户明细;维度是地区;时间是上个月;粒度可能按客户、城市或日期;过滤是华东;实体是客户。
若用户说“按周看各渠道收入趋势”,指标是收入,维度是渠道,时间范围还缺失,粒度是周。系统可以先识别缺口,再决定使用默认范围还是澄清。
解析结果不等于业务定义已经确定。“收入”仍可能对应下单、支付、确认或净收入。槽位让歧义显性化,使后续模块知道缺的是哪一种信息,而不是把整个句子交给模型一次猜完。
结构化解析还便于 Trace。错误 SQL 出现时,可以判断是指标识别错、时间解析错、实体映射错,还是 Schema 检索错。
业务术语词典解决什么
业务词典连接用户语言与数据语言。
每个术语可以保存标准名称、同义词、定义、可选口径、适用数据域、对应指标或字段、时间语义、版本和负责人。“新增客户”可能映射注册事件,“付费客户”映射支付成功事实,“活跃客户”则可能按产品线有不同定义。
词典不是简单同义词替换。它要表达条件和歧义。例如“销售额”在经营报表里可能指含税订单金额,在财务报表里可能指确认收入。系统需要根据当前数据域和用户角色缩小候选,仍有多个合法口径时请求确认。
词典还要与权限结合。某个敏感指标即使语义匹配,当前用户无权访问时不能进入候选 Schema,更不能在澄清问题里泄露其存在和细节。
用户确认某个口径后,可以把选择保存在当前查询 State,后续追问沿用,但不能自动升级成所有用户的全局定义。
Schema 召回不能只搜表名
候选生成可以组合多路信号:表和列描述的语义相似;业务术语映射;指标目录;实体与示例值匹配;数据域和用户角色;历史正确样例;精确关键词。
例如问题涉及“退款后的支付收入”,语义召回可能命中支付表和退款表,术语词典命中净收入指标,关系图补充订单主键。只搜表名可能只找到一张 payment 表,遗漏退款调整。
候选表要带入相关列,而不是把每张表全部字段送入模型。保留主键、外键、指标字段、过滤字段、时间字段和必要维度字段。敏感或无关列继续排除。
召回阶段追求“正确表列在候选里”,但候选不能无限扩大。可以先按数据域和权限硬过滤,再语义召回和重排。阈值与候选数量需要根据评测集校准,不应在没有数据时给固定数字。
找到表还不够,还要补齐 Join 路径
用户问题常跨越事实表和维表。单独召回到订单、客户和地区表,不代表模型知道怎样连接。
系统可以维护 Schema Graph:节点是表,边记录外键、候选连接键、基数关系、有效条件和方向。召回到目标表后,在图中寻找允许的最短或最可信连接路径,并补齐中间桥接表。
连接信息要包含一对一、一对多或多对多关系。若订单明细与标签表都是一对多,直接连接会造成行数膨胀。模型需要知道先聚合、去重或使用存在性子查询,而不是只拿字段名拼 JOIN。
并非所有数据库都声明完整外键。此时可以由数据团队维护关系元数据,或从已审核查询中提取候选关系,但必须标明可信度和来源。不能把列名相同当作可连接证明。
最终送给生成器的是一个连通的最小 Schema 子图:目标指标、过滤与分组字段、时间字段、必要主外键和业务说明。

候选表需要通过可信关系形成连通子图,不能让模型自由猜连接键。
歧义可以分成哪些类型
第一类是指标歧义。收入、用户、订单、活跃等业务词有多个口径。
第二类是时间歧义。上个月、最近一年、同比、当日可能涉及自然周期、滚动窗口、时区和业务日。
第三类是实体歧义。同名客户、产品简称、地区层级或组织名称可能对应多个编码。
第四类是粒度歧义。“查客户”可能要明细列表,也可能要数量;“趋势”可能按天、周或月。
第五类是范围歧义。“华东”按注册地、订单收货地、门店区域还是销售组织归属。
第六类是权限与可用性歧义。用户想要的指标存在,但当前只能访问脱敏或聚合版本。
将歧义分类后,澄清问题才能针对真正缺口。泛泛地问“请提供更多信息”对用户没有帮助。
什么时候必须澄清,什么时候可以使用默认值
如果不同解释会改变核心指标、表、Join 路径或权限,就应该澄清。若只是展示排序或默认分页,产品已有明确约定,可以使用默认值并在结果中说明。
澄清问题应最小化。不要一次列出十个数据库字段让用户选择。可以问:“这里的活跃客户,是指上个月登录过,还是上个月完成过支付?”两个选项直接对应候选口径。
如果候选解释很多,可以先根据用户角色、当前报表域和历史上下文缩小,再问区分度最大的一个问题。用户回答后更新结构化槽位和 Schema 候选,而不是把回答只追加到对话末尾。
不能用置信度高就掩盖高风险歧义。模型很确信地选择错误财务口径,后果仍然严重。是否澄清还要考虑指标风险、执行影响和结果用途。
默认值必须可见。系统使用自然月、北京时间、支付成功金额或明细上限时,应在查询解释中明确,让用户能纠正。
一个完整例子:查上个月华东的活跃客户
第一步解析槽位:实体是客户,地区条件是华东,时间是上个月,活跃口径未定义,输出粒度未定义。
第二步查术语词典,发现当前业务域里“活跃客户”有登录活跃与支付活跃两种有效定义。“华东”也可按客户注册地址或订单收货地解释。
第三步提出高信息量澄清:“你要看登录过的客户,还是完成过支付的客户?地区按客户注册地还是订单收货地?”如果产品希望一次只问一个问题,先问会改变事实表的活跃口径,再问地区字段。
用户回答“完成支付,按收货地,给客户明细”。系统据此选择支付事实、订单与地址维表,补齐连接路径,选择客户 ID、客户名、支付时间和地区字段,并把“上个月”解析成当前时区下的上一自然月。
生成 SQL 前,最小 Schema 已经包含明确口径和关系。即使最后 SQL 仍可能出错,错误空间已经从上百张表缩小到一个可解释子图。
多轮追问怎样沿用上下文
用户得到结果后说“再按城市汇总”,这不是一个全新查询。系统应沿用已经确认的支付活跃、收货地区域和上月时间,只把粒度从客户明细改成城市聚合。
State 需要保存原问题、已确认槽位、默认值、Schema 版本、候选子图和用户修改。若用户说“时间改成今年”,只更新对应槽位并重新检查分区与可用表。
历史上下文不能无条件沿用。用户切换数据域或明确说“换成登录活跃”,旧口径应被替代。当前确认高于模型从历史推断的偏好。
多轮查询的测试要覆盖指代、条件追加、条件撤销、粒度变化和口径改写,避免系统每轮重新猜 Schema 或错误叠加旧过滤。
怎样评估 Schema 选择和澄清
不能只看 SQL 是否执行成功。错误表和错误口径也可能返回一张看似合理的结果。
评测样本应保存用户问题、业务定义、允许的表列集合、必要 Join 关系、歧义标签、期望澄清问题和最终意图。对同一表达设计不同业务域,测试系统是否使用正确作用域。
分层指标可以看:目标表是否进入候选;关键列是否召回;最小子图是否包含必要关系;无关 Schema 是否过多;业务术语映射是否正确;该澄清时有没有问;不该澄清时是否直接处理;用户回答后槽位是否正确更新。
最终 SQL 准确性属于后续层。Schema 选对但 SQL 写错,与 Schema 一开始就漏表,需要不同修复路径。
Badcase 也要分类回流。新术语补词典,表说明不清补元数据,关系漏失补 Schema Graph,澄清问题无效则改歧义策略。不要只把失败样本塞进 Few-shot,希望模型自己悟出数据库治理问题。

指标、时间、实体、粒度和范围歧义需要不同的澄清与默认策略。
常见的四种错误方案
第一种是只做向量 TopK 表召回。它可能找对语义相似表,却漏掉中间 Join 表和关键外键。
第二种是把历史 SQL 当唯一真相。历史查询可能使用旧口径、旧 Schema 或特定用户权限,只能作为带版本候选。
第三种是让模型自行发明业务定义。答案流畅不代表“活跃”口径正确。
第四种是每个模糊词都追问。过度澄清让系统不可用,应把产品默认、低风险展示选择和真正改变业务结果的歧义分开。
历史正确 SQL 能不能直接当 Few-shot
可以作为候选样例,但必须先验证它与当前问题处在同一数据域、Schema 版本、业务口径和权限范围。
一条历史 SQL 执行成功,只能证明它在当时环境中可运行。表可能已经迁移,指标定义可能更新,历史用户也可能拥有当前用户没有的字段权限。若系统只按问题相似度拿来做 Few-shot,模型会复制旧表、旧过滤或旧 Join。
更稳的样例库应保存原问题、结构化意图、使用的表列、口径版本、Schema 版本、审核状态和适用范围。召回后先做元数据兼容检查,只把仍然有效的结构模式提供给生成器。
Few-shot 还能帮助模型学习特定查询模式,但不能替代元数据字典与关系图。历史上从未出现的新口径、新表或新权限,仍要回到当前 Schema 决策。

历史样例、元数据、关系与澄清都要在当前版本和权限内验收。
面试官会怎样连续追问
追问一:为什么不把全部 DDL 放进长上下文
长上下文不能解决业务含义、权限和 Join 关系,还会引入大量相似字段干扰。动态裁剪的目标是得到最小但完整的连通 Schema。
追问二:Schema 召回只用 Embedding 可以吗
不够。需要结合业务词典、精确实体、指标目录、数据域、权限和关系图。向量相似只是一种候选信号。
追问三:怎样判断该不该问用户
看不同解释是否改变核心指标、数据源、Join、权限或高风险结果。能用明确产品默认解决的低风险项可以说明默认,不必全部追问。
追问四:找到了目标表,为什么还会生成错 SQL
可能漏了连接表、基数信息、时间口径或聚合粒度。Schema 选择要输出连通子图和业务说明,不只是表名列表。
追问五:业务词典谁来维护
由数据与业务负责人提供权威定义,系统记录版本和来源;Badcase 可以提出候选,但不能由模型静默改全局口径。
追问六:怎样证明澄清机制有效
建立带歧义标签和期望问题的评测集,分别测该问时能问、不该问时不打断,以及用户回答后 Schema 是否收敛。
从用户问题到最小 Schema:完整回答
大规模 Text2SQL 我会先做语义解析和 Schema Linking,而不是把全量 DDL 塞给模型。用户问题拆成指标、维度、时间、粒度、过滤和实体,通过业务术语词典、表列描述、指标目录、示例值与权限召回候选。然后在 Schema Graph 中补齐主外键和中间表,保留基数、时间语义和聚合说明,形成最小连通子图。如果指标、时间、实体或范围有多个合法解释,就根据风险和区分度提出最小澄清问题,用户确认后写回结构化 State。评估分层看表列召回、Join 路径、术语映射、澄清决策和最终 SQL,Badcase 分别回流元数据、词典、关系图与澄清策略。
Schema 选择与澄清,项目里要留下什么
- 是否能把问题拆成指标、维度、时间、粒度、过滤和实体。
- 元数据是否包含业务含义、单位、枚举、时间语义、权限和版本。
- Schema 召回是否组合语义、术语、指标、实体和数据域。
- 候选表是否补齐可信 Join 路径与基数关系。
- 最终上下文是否最小但完整,而非简单 TopK 表。
- 是否区分指标、时间、实体、粒度、范围和权限歧义。
- 澄清问题是否直接区分候选口径,避免泛泛追问。
- 多轮修改是否更新结构化槽位,而非不断拼接自然语言。
- 评估是否把 Schema 选择、澄清和 SQL 生成分层归因。
- 没有真实数据时,是否避免虚构准确率、表规模和收益数字。
Text2SQL 的上限不只由模型决定。把业务口径、Schema 关系和歧义处理做成可维护的语义层,才可能让“自然语言查数据”从演示变成可解释的工程链路。