这款 Text2SQL 技术为什么能对噩梦般的 JOIN 免疫

8 阅读1分钟

在 Text2SQL 领域,JOIN 一直是个“终极考场”。不少方案宣称在公开测试集上能达到 90% 以上的惊人准确率,但背后往往存在一个关键“水分”:许多测试是在预先做好的大宽表上进行的,规避了真实的、动态的多表关联挑战。一旦面对企业真实的、网状交织的数据环境,需要系统动态识别关联路径并生成正确的 JOIN 时,准确率便会经历“高台跳水”。在 Spider 这类标准多表数据集上,先进大语言模型(LLM)方案的执行准确率通常在 60%-82% 之间,而且需要投入极高成本。其中错误多集中在 JOIN 遗漏、关联错误等环节。这正是许多演示酷炫的工具难以在企业复杂场景中扎根的核心瓶颈。

行业也在探索从“概率生成”到“确定编译”的范式转变。主流路径如 Google、微软的方案,依赖更强大的 LLM 与检索增强生成(RAG)技术;而另一些研究思路(如 UNJOIN 框架)则尝试将多表模式“扁平化”为虚拟单表供 LLM 理解,再后置重构 JOIN。然而,这些方法的核心仍未摆脱对概率模型的依赖,将最复杂的关联逻辑暴露于 LLM 的“幻觉”风险之下。

润乾 NLQ 选择了一条不同的工程化路径。它没有让 AI 在 JOIN 迷宫中“猜路”,而是构建了一套基于“语义层”和确定性编译的架构,将复杂的关联逻辑转化为可预测、可验证的规则执行,从而在面对复杂 JOIN 时保持了稳定的高准确率。

为什么 JOIN 是 Text2SQL 的“噩梦”?

要理解润乾 NLQ 的突破,需看清当前主流技术路径的局限。问题核心在于,无论是端到端生成还是引入中间表示,其本质都依赖于 LLM 的概率性生成与泛化能力。模型根据所学到的海量模式和提示词,去“推算”出最可能的 SQL。

这种方法在简单查询上表现尚可,但面对业务中真实的复杂 JOIN 时,其短板暴露无遗。一个正确的多表关联查询,背后是严格的业务逻辑和精确的数据结构知识。然而,LLM 著名的“幻觉”在此是致命的——它可能自信地生成一个引用不存在字段或错误关联关系的 SQL。此外,企业的数据模型通常包含大量存在复杂关联的业务表,当试图将所有这些表的字段信息纳入上下文时,冗长的提示会使 LLM 难以兼顾全局、精确捕捉每一处关联细节,从而导致其无法可靠地推导出完整的关联图谱。

更根本的挑战在于,一般方法试图让 AI 直接解决一个复合问题:既要理解自然语言意图,又要精确匹配数据库模式,还要编排正确的 JOIN 逻辑。这就像让一个翻译同时兼任地图导航和交通调度,出错概率自然倍增。

举个例子,一个常见的业务需求是:“帮我列出各省的员工数量、产品数量和订单数量”。这听起来很直观。

但对应的 SQL 却是噩梦级的,能让许多 LLM“翻车”:

SELECT
COALESCE(T_1.F_1, T_2.F_1, T_3.F_1) AS "省",
T_1.F_2 AS "员工数",
T_2.F_2 AS "产品数",
T_3.F_2 AS "订单数"
FROM (
    SELECT
    T_1_2.PROVINCE AS F_1,
    COUNT(1) AS F_2
    FROM EMPLOYEE T_1_1
    LEFT JOIN CITY T_1_2 ON T_1_1.HOMECITY = T_1_2.CITYCODE
    GROUP BY T_1_2.PROVINCE
) T_1
FULL JOIN (
    SELECT
    T_2_3.PROVINCE AS F_1,
    COUNT(1) AS F_2
    FROM PRODUCT T_2_1
    LEFT JOIN SUPPLIER T_2_2 ON T_2_1.SUPPLIERID = T_2_2.SUPPLIERID
    LEFT JOIN CITY T_2_3 ON T_2_2.CITY = T_2_3.CITYCODE
    GROUP BY T_2_3.PROVINCE
) T_2 ON T_1.F_1 = T_2.F_1
FULL JOIN (
    SELECT
    T_3_2.PROVINCE AS F_1,
    COUNT(1) AS F_2
    FROM ORDERS T_3_1
    LEFT JOIN CITY T_3_2 ON T_3_1.SHIPCITY = T_3_2.CITYCODE
    GROUP BY T_3_2.PROVINCE
) T_3 ON COALESCE(T_1.F_1, T_2.F_1) = T_3.F_1

这段 SQL 的难点在于

  • **多表关联与维度对齐:**需要从三个独立的事实表(employees/products/orders)分别聚合,再按省份维度对齐

  • **缺失值处理:**并非所有省份在三张表中都有数据,需要 FULL OUTER JOIN 和 COALESCE 处理

  • **聚合层级匹配:**需要在子查询中完成各自聚合,再在外部进行关联,而且子查询还要 JOIN,还不止一个。

让一个没有深刻理解企业数据关系的 LLM,一次性“蒙对”这种逻辑链,概率极低。它可能会错误地使用 INNER JOIN 导致数据丢失,或完全搞错对齐方式。这正是业界在复杂查询场景下准确率暴跌至 30% 左右的核心原因——模型是在“生成”,而非“理解”。

免疫原理:润乾 NLQ 的确定性编译架构

上面那个噩梦级的 SQL,其实是润乾 NLQ 从“各省的员工数量、产品数量和订单数量”这句话生成的(因为程序生成,里面的中间表名明显是没有业务意义的),Text2SQL 中的复杂 JOIN 在这里免疫了。

与大多数依赖 LLM 生成 SQL(或中间层)的方案不同,润乾 NLQ 构建了一套多层确定性编译架构,将 Text2SQL 这个复杂的认知问题,分解为“语义转写”、“逻辑编排”与“关联生成”多个可验证的工程阶段。其完整路径为:自然语言 → 规范文本 → MQL(模型查询语言) → DQL(关联查询语言) → SQL。它将最易出错的多表关联逻辑(JOIN),从依赖概率生成的 LLM 任务中彻底剥离,交由基于确定规则的 DQL 引擎处理。

DQL 消除关联

DQL(Dimensional Query Language)是此架构中解决 JOIN 难题的核心。其设计哲学是进行一场根本性的思维转换:从关心“表如何连接”的数据库思维,转向关心“想要什么数据”的对象思维。这主要通过两大核心机制实现:“外键属性化”与“按维对齐”。

1. 外键属性化:用点号(.)替代复杂 JOIN
DQL 将传统 SQL 中多对一的外键关联,抽象为类似“对象. 属性”的访问方式。例如,在传统 SQL 中,要查询“员工的部门名称”,需要明确地写出 SELECT department.name FROM employee JOIN department ON employee.department_id = department.id。而在 DQL 中,这可以直接表达为 employee.department.name。系统会根据预定义的语义层模型,将这个点号路径编译为正确的 LEFT JOIN 链。查询语句极度简洁,且符合人的直观思维,无需再记忆和编排复杂的表连接关系。

2. 按维对齐:处理“各自为政”的并行聚合
“各省员工数、产品数、订单数”这类需求,是“按维对齐”的经典场景。其特点是:需要从多个没有直接外键关联的事实表中分别聚合数据(如员工表、产品表、订单表),然后按照一个共同的维度(如“省”)将结果对齐展示。
在 SQL 中,这需要编写包含多个子查询和 FULL JOIN 的冗长语句,逻辑复杂且极易出错。而 DQL 的“按维对齐”机制则优雅地解决了此问题:它允许每个表作为独立的数据对象进行聚合,只需声明大家共同对准的维度即可,无需关心这些事实表彼此之间如何连接。

全流程解析

以“各省员工数、产品数、订单数”为例

第一步:自然语言 → 规范文本

用户的问法被规整为清晰的意图表述。这个过程可以由 LLM 辅助完成,但 LLM 的任务被大大简化了:它只需做“转写”,不需要理解数据结构。

第二步:规范文本 → MQL(声明逻辑意图)
NLQ 引擎会依据预先配置好的“业务词典”(里面定义了“省”、“员工”、“产品”、“订单”等概念具体对应哪些表、哪些字段),生成下面的 MQL 语句。MQL 的核心作用是声明分析维度和度量指标,而非描述具体关联。

SELECT
  EMPLOYEE.count(1) AS 员工数,
  PRODUCT.count(1) AS 产品数,
  ORDERS.count(1) AS 订单数
ON Province ASFROM EMPLOYEE
  BY 籍贯省 
JOIN PRODUCT
  BY 供应商省 
JOIN ORDERS
  BY 发货省 

MQL 仅表达了“按省对齐统计”的业务意图。

第三步:MQL → DQL(生成精确对象路径与对齐逻辑)
这是关键一步。DQL 引擎会执行两项核心转换:

**外键属性化转换:**将 MQL 中简化的 BY 字段,解析为完整的对象属性路径。这需要查询语义层模型。

  • BY 籍贯省 → BY EMPLOYEE.HOMECITY.PROVINCE (意为:员工. 籍贯所在城市. 所属省份)

  • BY 供应商省 → BY PRODUCT.SUPPLIER.CITY.PROVINCE (意为:产品. 供应商. 所在城市. 所属省份)

  • BY 发货省 → BY ORDERS.SHIPCITY.PROVINCE (意为:订单. 发货城市. 所属省份)

**按维对齐建模:**识别出这是一个多事实表按共同维度(Province)对齐的需求,并采用 FULL JOIN 进行组织。

转换后,会生成类似如下的 DQL 语句:

SELECT 
    EMPLOYEE.count(1),
    PRODUCT.count(1), 
    ORDERS.count(1) 
ON Province 
FROM EMPLOYEE BY EMPLOYEE.HOMECITY.PROVINCE 
FULL JOIN PRODUCT BY PRODUCT.SUPPLIER.CITY.PROVINCE 
FULL JOIN ORDERS BY ORDERS.SHIPCITY.PROVINCE

这条 DQL 语句清晰地体现了对象思维:三个表独立统计,通过 FULL JOIN 并列,统一向 Province 维度对齐。点号语法描述了各自获取“省”信息的深层路径。

第四步:DQL → SQL(编译为数据库指令)

最终,DQL 引擎将包含了精确关联路径的 DQL 中间表示,确定性地编译为如前文所示的、包含多层子查询和 FULL JOIN 的复杂标准 SQL。整个转换链条从 MQL 开始便是确定性的,彻底杜绝了“幻觉”SQL 的产生。

更多实例

基于维度对齐和确定性编译的思想,润乾 NLQ 能够系统性地化解各类让 Text2SQL 方案棘手的 JOIN 难题。不仅能处理前文所述的跨表多维统计,还能轻松应对以下多种复杂关联查询场景:

带有聚合结果过滤的查询

业务查询:“找出订单总金额超过 20 万元的女员工。”

对应 SQL

SELECT e.Name AS 员工姓名, e.Gender AS 性别, SUM(o.Amount) AS 订单金额
FROM Employees e
INNER JOIN Orders o ON e.EmployeeID = o.SalesPersonID
WHERE e.Gender = '女'
GROUP BY e.EmployeeID, e.Name, e.Gender
HAVING SUM(o.Amount) > 200000

包含时间智能的多表查询

业务查询:“去年北京发往青岛的订单”

对应 SQL

SELECT
  YEAR(T_1_1.SHIPDATE) AS "发货日期_Year",
  T_1_1.SHIPCITY AS "发货城市",
  T_1_2.CITYCODE AS "客户城市",
  T_1_1.ORDERID AS "订单编码",
  T_1_1.SIGNDATE AS "签单日期",
  T_1_1.SHIPDATE AS "发货日期",
  T_1_1.RECEIVEDATE AS "收货日期",
  T_1_1.AMOUNT AS "订单金额"
FROM ORDERS T_1_1
LEFT JOIN CUSTOMER T_1_2 ON T_1_1.CUSTOMERID = T_1_2.CUSTID
WHERE (YEAR(T_1_1.SHIPDATE) = YEAR(DATEADD('yy', -1, NOW())))
  AND (T_1_1.SHIPCITY = 30101)
  AND (T_1_2.CITYCODE = 20201)

需要跨越多层表关联的查询

业务查询:“列出订单编号、日期、对应的产品名称以及供应商所在城市。”

对应 SQL

SELECT
  T_1_1.ORDERID AS "订单编码",
  T_1_2.SHIPDATE AS "订单日期",
  T_1_3.PRODUCTNAME AS "产品名称",
  T_1_4.NAME AS "供应商名称",
  T_1_4.CITY AS "供应商城市"
FROM ORDERDETAIL T_1_1
LEFT JOIN ORDERS T_1_2 ON T_1_1.ORDERID = T_1_2.ORDERID
LEFT JOIN PRODUCT T_1_3 ON T_1_1.PRODUCTID = T_1_3.PRODUCTID
LEFT JOIN SUPPLIER T_1_4 ON T_1_3.SUPPLIERID = T_1_4.SUPPLIERID

这些实例表明,无论是涉及聚合后过滤(HAVING)、时间智能与动态关联解析,还是跨越多个实体的长路径关联,润乾 NLQ 都能通过其确定性架构,将复杂的业务提问准确地编译为正确的多表 JOIN SQL。

润乾 NLQ 这套方案,说直白点,就是稳、省、简单、好接入。不靠 AI 去“猜”复杂的多表关联该怎么连,而是用一套可靠的规则引擎来“算”,所以结果非常准,不会出现时灵时不灵的情况。因为核心是规则计算而不是跑大模型,所以特别省钱,用普通的服务器就能跑起来,不用投钱买昂贵的显卡。整套系统也很轻便,能很容易地塞进现有的系统里,对于预算和 IT 能力有限的中小企业来说,是个能立刻用上、负担得起的智能问数工具。