业务故事站
P1 AIP

复杂分析:聚合、多表与排查

按月对比、多表关联、组合过滤,再到"答案不对劲"时如何看 SQL / 意图 / RAG 上下文定位问题。看完这 4 个故事,你就知道复杂问法的边界在哪、以及结果不对时往哪个方向查。

业务分析师 销售总监 数据工程师 聚合 多表关联 问题排查 共 4 个故事

能 / 不能速览

✅ 这个主题能做
  • 时间维度聚合:按月 / 按日期统计销售额,自动推荐折线图
  • 多表关联问法:订单 + 客户 + 商品三表 JOIN 都能生成
  • 组合过滤:分类 = 电子 且 金额 > 1000 这种 AND 条件
  • 答案排查:打开返回的 SQL / 意图 / RAG 上下文逐项核对
  • 结果列类型驱动的图表推荐(line / bar / pie / metric_card)
⛔ 这个主题做不了
  • 跨数据源 JOIN(不同数据源的表不能混在一起查)
  • 复杂分析:根因分析、趋势预测、异常归因等"分析"意图只打标,不深挖(自动多步分析需走 Agent / 工作流编排,NLQ 主链路不做)
  • RAG 是关键词匹配,口语化、省略式描述命中率不稳定(本体 / OAG 未建模时尤甚)
  • 自动修复上限 2 次:SQL 连续 3 次执行都失败就返回错误,仍要人工换问法重问
  • NLQ 本身无多轮记忆:每句独立处理,复杂问法必须把表、字段、条件一次说全

适用角色

本主题面向进阶使用者:

  • 业务分析师:把"要什么数"问得更复杂(时间、多表、组合条件),并学会自检答案。
  • 销售总监:看月度对比、品类结构这类结论型分析。
  • 数据工程师:答案不对时负责排查元数据(描述 / 同义词 / 表结构)这一侧。

能力速览(能做什么)

时间聚合

把"7 月和 8 月的销售额"翻译成按月份 GROUP BY,命中"时间列 + 数值列"时推荐折线图。

多表 JOIN

orders + customers + products 三表按主外键关联,客户名、商品名、分类都能查进结果。

组合过滤

多个条件的 AND / OR 组合(如 分类=电子 且 金额>1000)由 LLM 翻译为 WHERE 子句。

链路自检

每次响应携带 intent / confidence / sql_query / sql_explanation / rag_context / fix_attempts,供结果核对与排错。

失败自修复

SQL 执行报错时自动携带错误 + 可用列重建 prompt 重写,最多 2 次;响应里 fix_attempts 记录实际修复次数。

RAG 上下文

默认四路召回(metadata/knowledge/history/fewshot);本体 / OAG 命中时直接注入业务语义描述(rag_channels_used 标明实际通道)。

双层审计

复杂查询同样写 NLQ_QUERY 事件级审计;另写 AI_DECISION 决策级审计(retrieve→generate→execute),/admin/ai-audit 可回放决策链。

调整指南(怎么调整)

  • 时间问法:明确说"按月""7 月和 8 月"比"最近两个月"命中更稳;日期函数由 LLM 生成,返回空行先看 SQL 里时间格式与 order_date 是否匹配。
  • 关联问法:把关联对象点破,如"客户的姓名""商品的分类",比"看每个客户"更容易生成正确 JOIN。
  • 过滤问法:条件给全(表 + 字段 + 值),如"商品分类为电子的订单且金额大于1000";省略词容易让 LLM 漏条件。
  • 排查顺序:先看 intent / confidence(是不是被归错类)→ 再看 rag_context(相关表有没有进上下文)→ 最后看 sql_query(JOIN、WHERE 是否写对)。
  • 元数据侧:描述 / 同义词缺失时中文业务词常匹配不上,可用 ai_generate_descriptions=true 重新导入元数据补描述。

做得好的场景

在"单数据源 + 元数据齐全 + 问法直白"的前提下,复杂分析体验最好:
  • 月度对比秒出:销售月度趋势一句话出折线图,替代以前 SQL + Excel 透视表半小时。
  • 跨表查口径:客户名、商品名这些"要 JOIN 才知道"的信息,一句带出。
  • 可解释可排查:每个数字背后都有 SQL 和 RAG 上下文,结果不对能定位到元数据还是模型。

限制与不足

以下是明确的边界,使用前先知道:
  • 无跨源 JOIN:只能在一个数据源的表之间关联,不同数据源的表不能混查。
  • analysis 意图只打标不深挖:问"为什么销量下降"会识别为 analysis,但 NLQ 主链路不会做多步归因分析(自动多步分析走 Agent / 工作流编排)。
  • 自动修复有上限:SQL 执行失败最多自动修复 2 次(共执行 3 次),修复耗尽可能返回"修复失败"的最终错误。
  • RAG 非向量:同义词/描述缺失时命中率低,容易回退全量 schema 增大 LLM 出错概率(可建模本体 / 启用 OAG 提升命中)。
  • 日期依赖启动时刻:演示订单日期相对服务启动时间生成,月度数据随重启变化。

场景故事

故事 1 销售总监按月对比:7 月和 8 月的销售额各是多少
背景
今天是 8 月上旬,李经理想在经营例会上讲"这两个月销售有没有起色"。他在 /chat 输入"查询7月和8月的销售额,分别多少",想直接拿两个数对比。
传统做法对比
以前要么找数据组写 SQL 按月汇总(排期 1 天起),要么把明细导进 Excel 做数据透视,半小时到半天;现在一句话,平台自己按月份分组。
角色
销售总监(消费结论型数据,不写 SQL)。
操作步骤
  1. 进入 /chat
  2. 输入"查询7月和8月的销售额,分别多少"并回车
  3. 核对返回 SQL 是否按月份分组
  4. 查看两行月度结果与折线图推荐
系统响应
平台生成按月聚合 SQL 并返回月度结果:
{
  "intent": "data_query",
  "confidence": 0.8,
  "sql_query": "SELECT strftime('%Y-%m', order_date) AS month, SUM(sales_amount) AS total FROM orders WHERE strftime('%Y-%m', order_date) IN ('2026-07','2026-08') GROUP BY month",
  "sql_explanation": "按年月分组,统计 7 月和 8 月的销售额",
  "query_result": { "columns": ["month","total"], "rows": [["2026-07","995"],["2026-08","4480.5"]] },
  "visualization": { "chart_type": "line", "reason": "contains time and numeric columns, recommend trend line chart", "x_axis": "month", "series": ["month","total"] }
}
前端渲染成一条简单的月度趋势折线。
结果洞察
7 月 995、8 月 4480.5,8 月才过了几天就已是 7 月的 4 倍多。李经理注意到平台自动用 strftime 按月分组,并因为"时间列 + 数值列"推荐了折线图而非表格——正是对比趋势想要的形态。
调整建议
想看完整 3 个月(含 6 月)就把范围说成"最近三个月按月统计";日期格式是 LLM 按 SQLite 方言生成的,若返回空行,检查 order_date 的存储格式是否匹配 strftime 的写法。
动手试一试
登录:admin / admin1。页面路径:/chat。输入内容:"查询7月和8月的销售额,分别多少"。预期结果:返回 2 行月度销售额(7 月约 995 / 8 月约 4480.5),图表推荐 line(折线图)。
限制提示
演示订单日期相对服务启动时刻生成,重启后月份分布会变,月度数字只作演示;跨数据源的时间对比(如把两个库的订单按月份拼一起)当前不支持。
故事 2 三表关联:查每个客户的电子类商品购买数量
背景
王姐想了解"电子品类都卖给了谁"。这个问题的答案藏在三张表里:orders(订单)要 JOIN customers(客户)拿名字,再 JOIN products(商品)拿分类。她输入"查询每个客户的电子类商品的购买数量"。
传统做法对比
以前要手写两条 JOIN 的 SQL,或者用三个 VLOOKUP 串起来,出错率高,一般要数据组帮忙;现在一句话,三表关联由平台生成。
角色
业务分析师(要跨表口径,不写 SQL)。
操作步骤
  1. 进入 /chat
  2. 输入"查询每个客户的电子类商品的购买数量"并回车
  3. 核对返回 SQL 是否 JOIN 了 customers 和 products
  4. 查看结果与图表推荐
系统响应
平台生成三表 JOIN 的 SQL 并返回按客户分组的数量:
{
  "intent": "data_query",
  "confidence": 0.8,
  "sql_query": "SELECT c.customer_name, SUM(o.quantity) AS total_qty FROM orders o JOIN customers c ON o.customer_id = c.customer_id JOIN products p ON o.product_id = p.product_id WHERE p.category = '电子' GROUP BY c.customer_name",
  "sql_explanation": "关联客户与商品表,筛选电子分类,按客户统计购买数量",
  "query_result": { "columns": ["customer_name","total_qty"], "rows": [["张三","30"],["李四","20"],["王五","0"]] },
  "visualization": { "chart_type": "bar", "reason": "contains one dimension and numeric columns, recommend bar chart", "x_axis": "customer_name", "series": ["customer_name","total_qty"] }
}
结果洞察
电子类:张三 30 件(智能手表 10 + 20)、李四 20 件(蓝牙耳机 5 + 智能手表 15)、王五 0 件(他买的办公椅是家具类)。王姐核对后确认 SUM 只统计了电子分类,三表关联逻辑正确。
调整建议
想看电子类金额而非数量,把"数量"换成"销售额"重问;王五这类"0"来自 LEFT/内连接语义差异,若想显示全部客户可加"包括没有订单的客户"。
动手试一试
登录:admin / admin1。页面路径:/chat。输入内容:"查询每个客户的电子类商品的购买数量"。预期结果:返回 3 行(张三 30 / 李四 20 / 王五 0),推荐 bar 柱状图。
限制提示
JOIN 关系靠 LLM 从元数据推断,元数据里没有主外键描述时可能连错;跨数据源(不同库的表)JOIN 不支持,三表关联仅限同一数据源。
故事 3 组合过滤:电子分类中金额大于 1000 的订单
背景
王姐要给渠道复盘"高客单的电子订单"。她心里有两个条件:商品分类 = 电子,且订单金额 > 1000。她在 /chat 输入"查询电子分类中金额大于1000的订单"。
传统做法对比
以前要在 Excel 里先筛选分类再筛选金额,两列条件反复切;数据量一大就卡。现在一句话把两个条件说清楚,WHERE 里自动拼 AND。
角色
业务分析师(多条件筛选)。
操作步骤
  1. 进入 /chat
  2. 输入"查询电子分类中金额大于1000的订单"并回车
  3. 核对 SQL 中 WHERE 是否同时含分类与金额条件
  4. 查看结果
系统响应
平台生成带两个条件的 SQL:
{
  "intent": "data_query",
  "confidence": 0.8,
  "sql_query": "SELECT o.order_id, o.sales_amount, p.product_name, p.category FROM orders o JOIN products p ON o.product_id = p.product_id WHERE p.category = '电子' AND o.sales_amount > 1000",
  "sql_explanation": "关联商品表,筛选电子分类且销售额大于 1000 的订单",
  "query_result": { "columns": ["order_id","sales_amount","product_name","category"], "rows": [["3","1990","智能手表","电子"],["5","1492.5","智能手表","电子"]] },
  "visualization": { "chart_type": "table", "reason": "default table view", "x_axis": "order_id", "series": ["order_id","sales_amount","product_name","category"] }
}
结果洞察
命中 2 笔:订单 3(智能手表,1990 元)、订单 5(智能手表,1492.5 元)。蓝牙耳机(995)和办公椅(998)都被正确过滤掉。王姐确认 WHERE 里 category='电子' 和 sales_amount>1000 是 AND 关系,没漏条件。
调整建议
想要"或"关系(电子或金额大于1000)要明说"或者",否则 LLM 默认 AND;想按金额排序在问句里加"从高到低",LLM 会拼 ORDER BY。
动手试一试
登录:admin / admin1。页面路径:/chat。输入内容:"查询电子分类中金额大于1000的订单"。预期结果:返回 2 行(订单 3 / 订单 5,均为智能手表,电子类)。
限制提示
多条件组合依赖 LLM 正确理解"且/或",省略连词时默认 AND;条件里的字段名必须存在于元数据,写错列名会执行报错。
故事 4 答案不对劲:用 SQL / 意图 / RAG 上下文定位是元数据还是模型问题
背景
王姐问"查询电子类商品的总销售额",平台返回 6470.5——但她心里期望只有电子品类,不该等于全表总额。她把这条消息发给张工(数据工程师),两人按"链路自检"的思路逐项排查。
传统做法对比
以前黑盒 BI 报错只能"重查一遍"或提工单等回复;现在返回里自带 intent / confidence / sql_query / rag_context,把"怎么理解的"全摊开,几分钟就能定位。
角色
业务分析师(发现数字异常)+ 数据工程师(排查元数据 / RAG 上下文)。
操作步骤
  1. 先看 intent 与 confidence:是否被识别成 data_query(0.8)而非别的意图
  2. 再看 rag_context:products 表有没有进入上下文
  3. 最后看 sql_query:有没有 JOIN products、WHERE 里有没有分类条件
  4. 按定位结果换问法重查或补元数据
系统响应
本次返回的 sql_query 是 SELECT SUM(sales_amount) AS total FROM orders——没有 JOIN products,也没有 WHERE 分类条件,且 fix_attempts: 0(SQL 能正常执行,自动修复只在"执行报错"时触发,语义漏条件不会触发);rag_context 里因为"电子"没命中任何表/列描述,已回退为全量 schema(orders / customers / products 三表齐全)。管理员还可以去 /admin/ai-audit 按这条查询的 trace_id 回放 retrieve→generate→execute 三步,看上下文到底注入了什么。
结果洞察
定位结论:元数据没问题(products 在上下文里),是模型这轮没把"电子类"翻译进 SQL(属 LLM 生成问题,不是元数据问题)。王姐换一种更直白的问法"查询商品分类为电子的订单的销售额之和",平台返回正确结果 5472.5(995+995+1990+1492.5)。
调整建议
重问时把表和条件点破("商品分类为电子""订单销售额之和");若多次重问仍漏条件,就检查元数据——演示库导入元数据时未开 LLM 描述(ai_generate_descriptions=false),可用 true 重导,给 category 等列补上描述与同义词,提升 RAG 命中率。
动手试一试
登录:admin / admin1。页面路径:/chat。输入内容:"查询商品分类为电子的订单的销售额之和"。预期结果:返回 5472.5;先前的问法可能返回全表总额 6470.5,两种结果对照即可理解排查思路。
限制提示
自动修复只处理"执行报错"(语法/列名/方言错误),不处理"语义漏条件"这种能跑但结果不对的情况——此时 fix_attempts=0,换问法是主要手段;RAG 是关键词匹配,中文业务词在无描述元数据下经常匹配不上、回退全量 schema——可建模本体或启用 OAG 提升命中。

常见问题

为什么多表查询有时 JOIN 得对,有时 JOIN 得错?

JOIN 关系由 LLM 根据 RAG 提供的 schema 推断,没有主外键描述时靠猜。提高命中率的方法:问句里点破要关联的字段("客户姓名""商品分类"),或让数据工程师给列补描述 / 同义词。

analysis 意图是不是等于"自动做分析"?

不是。当前 analysis 只是意图标签(识别出你在问分析类问题),不会自动做根因、预测、多步归因。要具体数还得把问题问成数据查询,例如直接要"按月销售额"。

答案明显不对时该信哪个字段?

按顺序看:① intent / confidence(理解对不对)→ ② rag_context + rag_channels_used(相关表有没有进来、走的是 metadata 还是本体/OAG)→ ③ sql_query + fix_attempts(JOIN、WHERE、GROUP BY 是否写对、有没有触发自动修复)。前两者定位元数据 / RAG 问题,后者定位模型生成问题;管理员还能在 /admin/ai-audit 回放决策链确认。

能不能跨两个数据源查?

不能。MVP 的 NLQ 只能在一个数据源内部执行 SQL,跨数据源 JOIN 不在当前能力范围内;要跨源只能分别查再在外部合并。

有没有办法减少 LLM 出错的概率?

短期:问法直白、条件带全、点破表名字段名。长期:① 用 ai_generate_descriptions=true 重新导入元数据补描述与同义词,提升 RAG 命中;② 在本体建模页给对象/属性/链接建语义模型,命中后直接注入业务语义(ontology_hit=true);③ 启用 OAG 对象路(foundry.oag.enabled=true,需 Foundry + column_map 配置),让口径公式结构化注入、LLM 不猜语义。

主题小结

一句话:复杂分析能覆盖月度聚合、三表关联、组合过滤,但"能生成 SQL"不等于"一定对"。遇到答案不对劲,按 意图 → RAG 上下文 → SQL 三步定位:元数据问题找张工补描述,模型问题换问法重问。别指望黑盒,AIP 把链路摊开给你看,就是为了让你能自检。