ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Text2SQL 复杂多表关联评测:大模型在 5 表以上 Join 时的翻车实录

Text2SQL 复杂多表关联评测:大模型在 5 表以上 Join 时的翻车实录 Text2SQL 复杂多表关联评测大模型在 5 表以上 Join 时的翻车实录在评估大语言模型LLM的自然语言转 SQLText2SQL能力时很多通用的基准测试如 Spider 或 BIRD给出的准确率往往看起来高达 80%~90%。然而这些基准测试中的题目大多局限在 2 到 3 张小表之间的简单关联。一旦把测试推向工业级企业数仓面对涉及5 张以上大表关联包含事实表、桥接表、主维表、子维表与聚合配置表的真实复杂经营分析报表需求时各大主流大模型的翻车率呈现出断崖式上升。为了摸清当前前沿大模型在复杂关联场景下的真实边界我们抽取了生产数仓中 100 组具有代表性的“5 表至 8 表关联”分析需求对多款主流模型进行了严格的盲测。实测结果令人咋舌在未经子图拆解的前置工程干预下大模型单次生成多表复杂 SQL 的首次执行成功率Zero-shot Execution Accuracy平均只有不到 32%。-- 典型的 5 表关联复杂需求统计上周华东区不同品牌、不同渠道的妥投结算率与退款占比 -- 大模型生成的“翻车典型 SQL” SELECT b.brand_name, c.channel_name, COUNT(DISTINCT o.order_id) AS total_orders, -- 致命错误 1在多对多连接膨胀后直接 SUM 金额导致金额被放大数十倍 SUM(p.pay_amount) AS total_pay_amt, SUM(r.refund_amount) AS total_refund_amt FROM dwd_trade_order o -- 致命错误 2缺少桥接表的中间关联条件导致局部产生隐式笛卡尔积 JOIN dim_item_sku s ON o.sku_id s.sku_id JOIN dim_brand b ON s.brand_id b.brand_id JOIN dim_channel c ON o.channel_id c.channel_id -- 致命错误 3对退款表执行 LEFT JOIN却在 WHERE 语句中过滤退款状态导致连接隐式退化为 INNER JOIN LEFT JOIN dwd_order_refund r ON o.order_id r.order_id LEFT JOIN dwd_order_pay p ON o.order_id p.order_id WHERE r.refund_status 2 -- 导致未发生退款的正常订单全部被过滤掉 GROUP BY b.brand_name; -- 致命错误 4SELECT 中的 channel_name 未包含在 GROUP BY 列表中触发语法报错翻车四大派系深度解剖分析这 100 组错误用例大模型在多表关联中的“翻车套路”高度集中在以下四个深水区1. 结果集膨胀导致的“假聚合”计算Fan-out Aggregation Trap当一张订单事实表order同时与多条记录的支付明细表pay一个订单可能有多笔支付流水和物流包裹表package一个订单可能拆为多个包裹进行 JOIN 时多表关联会引发扇出效应Fan-out中间临时表的行数会变成几何级膨胀。大模型往往毫无防备地直接写出SUM(pay_amount)导致算出来的成交金额比实际真实流水翻了数倍。2.LEFT JOIN的“假外连接”退化如上述错误代码所示业务需求通常要求“统计所有订单并关联展示其退款情况无退款则填 0”。模型在 FROM 阶段正确使用了LEFT JOIN dwd_order_refund r但转头在WHERE子句中随手加了一句WHERE r.refund_status 2。根据 SQL 代数语义对于没有退款的订单r.refund_status必然为NULL而NULL 2计算结果为FALSE。这导致原本的左连接被强制退化为内连接Inner Join把 90% 没有发生退款的正常订单全给过滤掉了3. 桥接表连接条件遗漏引发笛卡尔积爆炸在包含 5 张以上维度的查询中实体之间的关系往往不是直接相连的而是通过“商户 $\to$ 店铺 $\to$ 类目 $\to$ 商品”形成多级链路。大模型在组装长达几十行的ON条件时极易遗漏某一跳的中间关联键例如写了JOIN dim_shop ON o.user_id dim_shop.user_id直接在数据库内部引发了局部笛卡尔积线上执行直接打满几十 GB 内存导致 OOM。4.ONLY_FULL_GROUP_BY语法与作用域混淆在 MySQL 8.0 或严格模式的数仓中SELECT中出现的非聚合列必须全部显式包含在GROUP BY中。模型在长 SQL 的末尾经常“丢三落四”遗漏一两个维度列直接触发数据库内核的语法拦截。[应对复杂多表 Text2SQL 的“子图拆解与 AST 回环”工程架构] [用户复杂查询需求: 涉及 6 张大表关联] │ ▼ ┌─────────────────────────────────┐ │ 1. 意图拆解与子查询分解 (Planner) │ │ - 子图 A: 订单基础事实 维表 │ │ - 子图 B: 支付流水局部聚合预计算 │ │ - 子图 C: 退款明细局部聚合预计算 │ └────────────────┬────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ 2. 生成带 CTE 结构的模块化 SQL │ │ (WITH pay_summary AS (...)) │ └────────────────┬────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ 3. 本地 AST 语义校验与模式修复 │ │ - 校验 LEFT JOIN WHERE 穿透 │ │ - 校验 ONLY_FULL_GROUP_BY 完整性│ └────────────────┬────────────────┘ │ ▼ [最终输出零语法与语义缺陷的高性能 SQL]工业级工程解法CTE 模块化拆解与 AST 闭环拦截要让 Text2SQL 能够稳定承接 5 表以上的硬核查询绝对不能指望模型“一步到位”吐出整段长 SQL必须引入工程化脚手架强制引入 CTECommon Table Expression拆解在 Prompt 约束中强制要求模型先对多对多关联的子表如支付、退款在WITH语句中完成预聚合Pre-aggregation消除扇出膨胀风险本地 AST 语法与连接语义自动校验在 SQL 返回给客户端前由 Python/Go 本地 AST 引擎静态扫描一旦发现LEFT JOIN的表字段出现在WHERE等值判断中立即自动重写为ON条件或触发 Prompt 局部重试。把复杂的拓扑拆成确定的模块用严密的编译期规则兜住概率模型的失误才能让智能取数真正走进核心业务的决策大盘。
返回列表