TRAE + SQLazy MCP 自动化编写 SQL 实践

 让 AI 替你写代码,让代码说业务的话

做数据分析写SQL的同学大多有过这样的体验:需求一句话就能说清,落到 SQL 却要写上几十行。一段三十行的 SQL,真正表达业务意图的通常只有几行,剩下的篇幅都在描述一件很机械的事------这两张表要怎么 join、那个比率要乘一百再保留两位小数、那几张维表要一层层连上来。写的人累,读的人更累:得先在脑子里把这些机械描述翻译掉,才能看见业务本身。

有没有办法让代码直接说业务的话?SQLazy 给出的答案是:可以。它是一门面向数据分析的查询语言,每一行几乎都对应一句业务语言------按月汇总销售额、算占比、排个序。写完之后,它既能在 SQLazy IDE 里直接执行,也能一键编译成标准 SQL,交给任意数据库去跑。也就是说,你不需要先学会 SQL 才能做数据查询------学会说业务的话,就够了。

而本文要讲的,是更进一步的实践:在 TRAE 里接入 SQLazy MCP 之后,连这几行业务化的代码都不用自己写了------你用自然语言描述需求,AI 自动生成 SQLazy 脚本、自动生成测试数据、自动验证结果,甚至能把存量 SQL 反向翻译成 SQLazy。下面先通过几组对比看看 SQLazy 有多简单,再手把手走一遍 TRAE + SQLazy MCP 的自动化流程。

一、先看一组对比:同一个需求,两种写法

下面用同一批示例数据(客户、订单、订单明细、零件、零件供应、供应商、国家、地区),把 SQL 写法和 SQLazy 写法放在一起,看看省下来的到底是什么。

1. percent():把占比这个口径,收敛成一个词

占百分之多少,几乎是所有报表里出现频率最高的口径。它的算法毫无争议------乘以 100、保留两位小数------但每次都要手写一遍 round(x * 100, 2),而且每个人写的位数、乘的位置还可能不一样,口径天然容易走样。现在有了 percent(x),语义等价于 round(x * 100, 2),一个函数把整个口径固定下来:看到 percent,就知道是百分比。

例:各运输方式的销售额占比。

SQL 写法

复制代码
select 运输方式,
       sum(订购金额) as 销售额,
       round(sum(订购金额) / (select sum(订购金额) from 订单明细) * 100, 2) as 销售额占比
from 订单明细
group by 运输方式
order by 销售额 desc

SQLazy 写法

复制代码
运输统计=订单明细:汇总 合计 订购金额 命名 销售额 分组 运输方式
全站=汇总 合计 销售额 命名 全站销售额
运输统计:计算列 percent(销售额/全站.全站销售额) 命名 销售额占比
排序 销售额 降序

SQL 里那行 round(...),读者要先定位子查询、再确认乘 100 的位置、最后数一数保留几位;而 percent(...) 一眼就是占比。口径被函数固化之后,换个人来写、换张表来算,结果都是同一个口径。

2. 关联不用再写主键:拼接、匹配的省略写法

关联条件里最没有信息量的一类,就是两边都是主键。既然表结构里已经声明了主键是什么,写代码时就没必要再重复一遍。SQLazy 支持三种省略:

· **两侧都省略:**两表按各自的主键关联(要求主键能一一对应);

· **只省略一侧:**该侧用自己的主键去匹配另一侧写出的关联列;

· **主子表关联:**用主表的主键关联子表时,主表和子表侧的关联字段都可以不写------子表只用复合主键的一部分就够了。

例 1 :按零件统计库存总价值,并补上零件名称与品牌。

SQL 写法

复制代码
select p.零件ID, p.零件名称, p.品牌,
       sum(ps.库存量 * ps.成本价) as 库存总价值
from 零件供应 ps
join 零件 p on ps.零件ID = p.零件ID
group by p.零件ID, p.零件名称, p.品牌

SQLazy 写法

复制代码
零件供应:汇总 合计 库存量*成本价 命名 库存总价值 分组 零件ID
拼接 关联表 零件 拼接列 零件名称,品牌

关键在第二行:库存的分组字段零件ID 自动成为结果集的主键,零件表的主键也是零件ID,两侧主键同名可对应,于是关联列一个都不用写------SQLazy自动按主键关联,代码更清爽。

例 2 :找出还没有任何供应商供应的零件。

SQL 写法

复制代码
select p.零件ID, p.零件名称
from 零件 p
where not exists (select 1 from 零件供应 ps where ps.零件ID = p.零件ID)

SQLazy 写法

复制代码
零件:匹配 关联表 零件供应 不存在

一行。not exists 子查询被压成了一个匹配......不存在,而且读起来就是它的字面意思。

3. 导出表支持「.」操作符:外键字段随用随取

补外键表列是另一类高频机械劳动:明细表里只有零件ID、供应商ID,要看懂就得把它们对应的名称一层层 join 上来。SQLazy的导出表功能支持 「 . 」操作符,可以直接顺着外键引用外键表的字段,多级外键还能链式书写。想补哪个字段就写哪个,不必先写一段取数语句把宽表拼出来。

例:延迟交货分析,补上零件、品牌、供应商与供应商所在国家。

SQL 写法

复制代码
select d.订单ID, d.零件ID, p.零件名称, p.品牌,
       s.供应商名称, n.国家名称 as 供应商国家,
       d.承诺到货日期, d.实际到货日期
from 订单明细 d
join 零件   p on d.零件ID   = p.零件ID
join 供应商 s on d.供应商ID = s.供应商ID
join 国家   n on s.国家ID   = n.国家ID
where d.实际到货日期 > d.承诺到货日期

SQLazy 写法

复制代码
订单明细:筛选 实际到货日期 > 承诺到货日期
导出表 追加 零件ID.零件名称, 零件ID.品牌, 供应商ID.供应商名称,供应商ID.国家ID.国家名称

四表的 join 被压缩成四个表达式,其中供应商ID.国家ID.国家名称是链式写法(订单明细 → 供应商 → 国家)。读代码时,视线不必在 join 区和 where 区之间来回跳,语序和给这些记录补上零件名、品牌、供应商名、国家名这句话完全一致。更实用的是:这些外键表字段可以等计算结束后再补,中间步骤始终是窄表,既省事也省心。

4. 综合案例:五行完成占比 + 外键 + 排序

把上面的能力放进同一个需求:统计每个客户的销售额及其占全站的百分比,补上客户名称与所属行业,按销售额从高到低排。

SQL 写法

复制代码
select c.客户ID, c.客户名称, c.行业,
       sum(o.订单金额) as 销售额,
       round(sum(o.订单金额) / (select sum(订单金额) from 订单) * 100, 2) as 销售额占比
from 订单 o
join 客户 c on o.客户ID = c.客户ID
group by c.客户ID, c.客户名称, c.行业
order by 销售额 desc

SQLazy 写法

复制代码
客户销售=订单:汇总 合计 订单金额 命名 销售额 分组 客户ID
全站=汇总 合计 销售额 命名 全站销售额
客户销售:计算列 percent(销售额/全站.全站销售额) 命名 销售额占比
导出表 追加 客户ID.客户名称,客户ID.行业
排序 销售额 降序

五行代码,每行一句业务语言:按客户汇总销售额 → 算全站总额 → 算占比 → 补客户名称与行业 → 排序。没有 join,没有子查询,也没有 round 里嵌套除法。更实际的收益是改起来轻松:想把口径从占全站改成占本行业,只改一行分组;想多带一个字段,只在导出表里加一项。

二、SQLazy 为什么比 SQL 更好学

当然,真正让 SQLazy 区别于直接写 SQL 的核心优势是以下这些:

分步可 验证 、可 审计 **:**SQLazy 的每一步都是独立的计算动作,每一步都可以单独执行、单独预览中间结果。写完一步就能看到这一步的输出,不需要等整个查询跑完才发现问题。review 时看的是步骤,不是百行嵌套------哪一步对、哪一步错,点开就知道。这是 SQLazy 最根本的优势:把 SQL 开发从一个不可审计的黑盒,变成一个可逐步验证的流程。

零幻 觉 、确定性 编译 **:**AI 生成 SQL 最大的问题是不可信:可能编造字段名、可能写错语法、可能幻觉出不存在的函数。SQLazy 把这个问题从根上解决了------AI 只负责把自然语言翻译成步骤化的逻辑,最终 SQL 由确定性编译器生成。同一份逻辑永远编译出同一份 SQL,不编字段、不幻觉。你不需要赌 AI 的正确率,编译器替你保证了正确性。

跨数据 库 **适配:**同一份 SQLazy 脚本,可以编译成 Oracle、MySQL、PostgreSQL、达梦等不同数据库的 SQL 方言。写一遍,到处跑------数据库迁移、跨库对比、国产化替代,都不需要重写查询。编译器负责处理各家 SQL 方言的差异,你只管业务逻辑。

存量 SQL 可倒 译 **:**已经有一堆写好的、没人敢动的祖传 SQL?AI 能把它反向翻译成等价的 SQLazy 分步脚本,然后每一步都可读、可改、可验证。翻译完之后,逻辑还是那个逻辑,但代码从晦涩冗长变成了简明易读,维护成本大幅降低,代码真正成为资产。

需求 变 更只改 对应 步 骤 **:**SQL 的需求变更往往意味着整段重写;而在 SQLazy 里,改一个筛选条件、换一个分组字段、加一个维度列,只需要动对应的那一步,其他步骤不受影响。AI 也不需要重新生成整段代码,只改变化的部分即可。

这些才是 SQLazy 真正的价值所在!前面举例内容只是在这个大框架上实现的代码逻辑的四个小优点。想了解更多,可以到官网论坛查阅 SQLazy 相关文章。

三、TRAE + SQLazy MCP 实战:你说需求,AI 写 SQLazy

SQLazy 已经足够简单,那还能不能再简单一点?能------让 AI 替你写。SQLazy 为 TRAE 提供了 SKILL 和 MCP 服务,接入之后,TRAE 里的 AI 助手可以直接读写 SQLazy 脚本、连接内存表和数据库验证结果。整个过程分三步准备、三段实战。

3.1 环境准备(三步)

第一步:安装 SQLazy IDE **。**从官网 https://www.raqsoft.com.cn/download-SQLazy 下载安装。启动后点击【工具/内存表】→【导入】,选择例子数据.ndb------这是本文示例用到的测试数据,实际使用时请替换成自己的数据。系统运行时会自动读取内存表的表结构、数据类型、主外键关系,并用内存表里的数据测试结果代码,所以把测试数据放进内存表,AI 验证代码时就有据可依。

第二步:启动 MCP **服务。**点击【工具/启动MCP服务】。注意:如果替换了例子数据,需要重启 MCP 服务。

第三步:在 TRAE 中启用 SQLazy-MCP **。**打开 SQLazy 安装目录下的 MCP/TraeCode 文件夹(不同版本目录名可能略有差异,以实际安装目录为准),在 TRAE 的 MCP 设置中激活 SQLazy-MCP。到这里,TRAE 就具备了读写 SQLazy 脚本、操作内存表和数据库的全部能力。

3.2 实战一:一句话自动生成查询代码

在 TRAE 对话框输入指令,先写 SQLazy 规划,再写查询目标:

复制代码
SQLazy规划 计算月销售额最长连续上涨了几个月?

按回车,等待输出。

输出里除了思考过程,最终会出现交付字样和生成的脚本文件名------AI 已经把结果代码写进了这个文件。用 SQLazy IDE 打开它:

复制代码
订单:汇总 合计 订单金额 命名 月销售额 分组 ymonth(订单日期) 命名 年月
分段 月销售额 未变大 命名 段号
汇总 计数 段号 命名 连续上涨月数 分组 段号
汇总 最大 连续上涨月数 命名 最长连续上涨月数

四行。逐行读,就是四句业务语言:按月汇总销售额 → 标记销售额环比未变大的分段 → 按段数一数连续上涨了几个月 → 取最大的那段。这个最长连续上涨问题如果用 SQL 写,窗口函数嵌套自关联起步,没有三层子查询根本下不来;而 SQLazy 的分段一个动词就把它说完了。更重要的是------这四行你还不用自己写,TRAE 已经替你写好;而且相信你已经发现,你居然能直接看懂它。

点击【执行】,结果直接出来。要落到数据库里跑?点击【工具/数据连接】连上数据库,再点击【程序/编译SQL】:

先选择目标数据库类型,然后点击编译按钮:

也可以选其它类型的数据库,点编译,一键出结果,比如选ORACLE:

从这一步可以体会到前述的跨数据库适配的好处。

SQL 已经生成好了,点击执行按钮:

编译出的 SQL 在数据库里执行,结果和 SQLazy 脚本完全一致(前提是内存表数据和数据库一致)。写的是 SQLazy,跑的是 SQL------学习 SQL 的那道坎,就这么迈过去了。

3.3 实战二:测试数据自动造

写查询之前得先有数据。SQLazy 的生成测试用例能力,可以按你的业务描述自动造数,而且会同时写入 .ndb 文件和 SQLazy IDE 当前连接的数据库------天然保证两边一致。

造数之前,先确保已打开 SQLazy IDE 且 MCP 服务在运行中 ,并在【工具/数据连接】里连上目标数据库(界面显示已连接)。然后在 TRAE 对话框输入 生成测试用例,后面跟上对表结构和数据逻辑的描述。例如描述 8 张表(地区、国家、零件、供应商、零件供应、客户、订单、订单明细)及各自字段,再说明数据逻辑:订单大概每年 3000~5000 条、覆盖 2022---2026 年;订单明细是订单的子表,一条订单对应 1~5 条明细;日期字段要符合业务相关性------发货日期晚于订单日期、承诺到货日期晚于发货日期、实际到货日期大多接近承诺日期;各 ID 字段按外键关系取自对应维表......

按回车,等待输出:

从输出提示中可以看到,结果数据已经同时写入 ndb 目录下的 .ndb 文件和 SQLazy IDE 当前连接的数据库。在 SQLazy IDE 中点击【工具/内存表】→【导入】,选择生成的 .ndb 文件:

通过这种方式造的测试数据,天然满足内存表 = 数据库,后面无论验证 SQLazy 代码还是比对 SQL 翻译结果,都不会因为两边数据不一致而误判。

小提示:如果数据库里或 ndb 目录下已有同名对象,系统会停下来询问( A 删除并替换 / B 保留原表 / C 自定义回答),按需选择即可;不选择会一直等待。

3.4 实战三:存量 SQL 一键倒译成 SQLazy

已经有一堆写好的 SQL?不用重写。先在【工具/数据连接】里连上存放这些表的数据库(它用于执行待翻译的 SQL,与 SQLazy 的运行结果做对比),然后在对话框输入 SQL 倒译,后面跟上 SQL 语句:

复制代码
SQL倒译 select
    供应商国家.国家名称 as 供应商国家,
    客户国家.国家名称 as 客户国家,
    year(订单明细.发货日期) as 年份,
    sum(订单明细.订购金额 * (1 - 订单明细.折扣率)) as 收入
from
    订单明细
    join 订单 on 订单明细.订单ID = 订单.订单ID
    join 客户 on 订单.客户ID = 客户.客户ID
    join 供应商 on 订单明细.供应商ID = 供应商.供应商ID
    join 国家 as 供应商国家 on 供应商.国家ID = 供应商国家.国家ID
    join 国家 as 客户国家 on 客户.国家ID = 客户国家.国家ID
where
    (
        (供应商国家.国家名称 = '法国' and 客户国家.国家名称 = '德国')
        or (供应商国家.国家名称 = '德国' and 客户国家.国家名称 = '法国')
    )
    and 订单明细.发货日期 between '2022-01-01' and '2026-12-31'
group by
    供应商国家.国家名称,
    客户国家.国家名称,
    year(订单明细.发货日期)
order by
    供应商国家.国家名称,
    客户国家.国家名称,
    year(订单明细.发货日期);

按回车,等待结果:

从输出结果里可以直接看到 SQL 执行结果与 .nsql 执行结果的逐项比对情况:

确认结果一致后,用 SQLazy IDE 打开生成的 .nsql 文件即可直接使用。存量 SQL 资产可以平滑迁移,新老两种写法在同一个工作流里各得其所。

四、复杂查询也不在话下

有人会问:简单查询当然好写,复杂查询呢?下面从实测案例里挑三个典型的 SQL 重灾区------多表 join、多层嵌套子查询、窗口函数------看看同样的需求,两种写法各是什么样子。这些案例的 SQLazy 代码,同样都是由 TRAE 通过一句 SQLazy规划 或 SQL倒译 指令自动生成的。

4.1 TPC-H Q7:五张表 join,按国家和年份统计收入

SQL 写法

复制代码
select
  供应商国家.国家名称 as 供应商国家,
  客户国家.国家名称 as 客户国家,
  year(订单明细.发货日期) as 年份,
  sum(订单明细.订购金额 * (1 - 订单明细.折扣率)) as 收入
from
  订单明细
  join 订单 on 订单明细.订单ID = 订单.订单ID
  join 客户 on 订单.客户ID = 客户.客户ID
  join 供应商 on 订单明细.供应商ID = 供应商.供应商ID
  join 国家 as 供应商国家 on 供应商.国家ID = 供应商国家.国家ID
  join 国家 as 客户国家 on 客户.国家ID = 客户国家.国家ID
where
  (
  (供应商国家.国家名称 = '法国' and 客户国家.国家名称 = '德国')
  or (供应商国家.国家名称 = '德国' and 客户国家.国家名称 = '法国')
  )
  and 订单明细.发货日期 between '2022-01-01' and '2026-12-31'
group by
  供应商国家.国家名称,
  客户国家.国家名称,
  year(订单明细.发货日期)
order by
  供应商国家.国家名称,
  客户国家.国家名称,
  year(订单明细.发货日期);

SQLazy 写法

复制代码
导出表 订单ID, 供应商ID, 发货日期, 订购金额, 折扣率, 供应商ID.国家ID.国家名称 命名 供应商国家, 订单ID.客户ID.国家ID.国家名称 命名 客户国家 
筛选 (发货日期 >= 2022年01月01日) 且 (发货日期 <= 2026年12月31日) 且 (((供应商国家 = "FRANCE") 且 (客户国家 = "GERMANY")) 或 ((供应商国家 = "GERMANY") 且 (客户国家 = "FRANCE")))
汇总 合计 订购金额 * (1 - 折扣率) 命名 收入 分组 供应商国家, 客户国家, year(发货日期) 命名 年份
导出表 供应商国家, 客户国家, 年份, 收入

五张表的 join,被「.」链式引用取代------供应商ID.国家ID.国家名称、订单ID.客户ID.国家ID.国家名称,顺着外键走就是了。人工检查也只是读四句话:取数、筛选、汇总、导出。

4.2 TPC-H Q20:三层嵌套子查询,找出有大量库存的供应商

SQL 写法

复制代码
select
  供应商.供应商名称,
  供应商.供应商地址
from
  供应商
  join 国家 on 供应商.国家ID = 国家.国家ID
where
  供应商.供应商ID in (
    select 零件供应.供应商ID
    from 零件供应
    where
      零件供应.零件ID in (
        select 零件.零件ID from 零件 where 零件.零件名称 like '%轴%'
      )
      and 零件供应.库存量 > (
        select 0.5 * sum(订单明细.订购数量)
        from 订单明细
        where
          订单明细.零件ID = 零件供应.零件ID
          and 订单明细.供应商ID = 零件供应.供应商ID
          and 订单明细.发货日期 >= '2022-01-01'
          and 订单明细.发货日期 < '2026-01-01'
      )
  )
  and 国家.国家名称 = 'CANADA'
order by
  供应商.供应商名称;

SQLazy 写法

复制代码
轴类零件=零件:筛选 (零件名称 串匹配 "%轴%")
订单明细:筛选 (发货日期 >= 2022年01月01日 且 发货日期 < 2026年01月01日)
汇总 合计 订购数量 命名 历史数量 分组 零件ID, 供应商ID
拼接 零件ID 供应商ID 关联表 零件供应 零件ID 供应商ID 拼接列 库存量 内连接
匹配 零件ID 关联表 轴类零件
候选供应=筛选 (库存量 > 0.5 * 历史数量)
供应商:导出表 供应商ID, 供应商名称, 供应商地址, 国家ID.国家名称
筛选 (国家名称 = "CANADA")
匹配 关联表 候选供应 供应商ID
排序 供应商名称
导出表 供应商名称, 供应商地址

SQL 版本里三层 in 子查询层层相扣,相关子查询还引用了外层字段,读的时候得拿着笔顺藤摸瓜。SQLazy 版本是一条从上到下的流水线:筛出轴类零件 → 汇总历史订购量 → 拼接库存 → 匹配 → 筛出候选 → 从加拿大供应商里再匹配。每一步都是一个中间变量,命名即注释。

4.3 窗口函数:每个客户订单金额的环比与累计

SQL 写法

复制代码
select 客户名称, 订单ID, 订单日期, 订单金额, 上一笔订单金额, 与上一笔差额,
       客户历史平均订单金额, 是否高于历史平均, 客户累计订单金额
from (
  select 客户.客户名称, 订单.订单ID, 订单.订单日期, 订单.订单金额,
    lag(订单.订单金额, 1) over (
      partition by 订单.客户ID order by 订单.订单日期, 订单.订单ID) as 上一笔订单金额,
    订单.订单金额 - lag(订单.订单金额, 1) over (
      partition by 订单.客户ID order by 订单.订单日期, 订单.订单ID) as 与上一笔差额,
    avg(订单.订单金额) over (partition by 订单.客户ID) as 客户历史平均订单金额,
    case when 订单.订单金额 > avg(订单.订单金额) over (partition by 订单.客户ID)
         then '高于平均' else '不高于平均' end as 是否高于历史平均,
    sum(订单.订单金额) over (
      partition by 订单.客户ID order by 订单.订单日期, 订单.订单ID
      rows between unbounded preceding and current row) as 客户累计订单金额
  from 订单
  join 客户 on 订单.客户ID = 客户.客户ID
) as t
order by 客户名称, 订单日期, 订单ID;

SQLazy 写法

复制代码
订单:导出表 订单ID,客户ID,客户ID.客户名称,订单日期,订单金额
排序 客户ID,订单日期,订单ID
计算列 平均 订单金额 命名 客户历史平均订单金额,
       订单金额[-1] 命名 上一笔订单金额,
       订单金额-上一笔订单金额 命名 与上一笔差额,
       条件((订单金额 > 客户历史平均订单金额) 则 "高于平均";否则 "不高于平均") 命名 是否高于历史平均,
       订单金额 累计 命名 客户累计订单金额 分区 客户ID
排序 客户名称,订单日期,订单ID
导出表 客户名称,订单ID,订单日期,订单金额,上一笔订单金额,与上一笔差额,客户历史平均订单金额,是否高于历史平均,客户累计订单金额

lag(...) over (partition by ... order by ...) 要写两遍,avg over 也要写两遍,再加一句 rows between unbounded preceding and current row------这些恰恰是 SQL 学习曲线最陡的部分。SQLazy 用订单金额-1表示上一行,用分区 客户ID表示按客户分区,用订单金额 累计表示累计求和。窗口函数的三个概念------分区、排序、帧------全部变成了字面词汇。

4.4 TPC-H Q8:七张表 join,按年份统计巴西市场份额

SQL 写法

复制代码
select
	年份,
	sum(case when 供应商国家.国家名称 = 'BRAZIL' then 金额 else 0 end) / sum(金额) as 市场份额
from
	(
	select
		year(订单.订单日期) as 年份,
		订单明细.订购金额 * (1 - 订单明细.折扣率) as 金额,
		供应商国家.国家名称 as 供应商国家名称						
	from
		订单明细
	join 订单 on 订单明细.订单ID = 订单.订单ID
	join 客户 on 订单.客户ID = 客户.客户ID
	join 国家 as 客户国家 on 客户.国家ID = 客户国家.国家ID
	join 地区 on 客户国家.地区ID = 地区.地区ID
	join 供应商 on 订单明细.供应商ID = 供应商.供应商ID
	join 国家 as 供应商国家 on 供应商.国家ID = 供应商国家.国家ID
	join 零件 on 订单明细.零件ID = 零件.零件ID
	where
		地区.地区名称 = 'AMERICA'
		and 订单.订单日期 between '2022-01-01' and '2026-12-31'
		and 零件.零件类型 = 'PROMO PLATED STEEL'
	) as 全部国家								
group by
	年份
order by
	年份;

SQLazy 写法

复制代码
订单明细:导出表 订购金额, 折扣率, 订单ID.订单日期, 订单ID.客户ID.国家ID.地区ID.地区名称, 供应商ID.国家ID.国家名称 as 供应商国家名称, 零件ID.零件类型
筛选 (地区名称 = "AMERICA") 且 (零件类型 = "PROMO PLATED STEEL") 且 (订单日期 >= 2022年01月01日) 且 (订单日期 <= 2026年12月31日)
计算列 year(订单日期) 命名 年份, 订购金额 * (1 - 折扣率) 命名 金额, 条件(供应商国家名称 = "BRAZIL" 则 订购金额 * (1 - 折扣率) 否则 0) 命名 巴西金额
汇总 合计 巴西金额 命名 巴西金额合计, 合计 金额 命名 总金额 分组 年份
计算列 巴西金额合计 / 总金额 命名 市场份额
排序 年份
导出表 年份, 市场份额

七张表的 join 加一个子查询套 case when,在 SQLazy 里变成一句宽表取数 → 筛选 → 计算列 → 汇总 → 计算占比 → 排序 → 导出,共 7 步。子查询被压成计算列,case when 被条件函数取代,读代码就是读业务流程。

4.5 TPC-H Q9:六表 join 加双字段关联,按国家和年份统计零件利润

SQL 写法

复制代码
select
	国家名称,
	年份,
	sum(利润) as 总利润
from
	(
	select
		国家.国家名称 as 国家名称,
		year(订单.订单日期) as 年份,
		订单明细.订购金额 * (1 - 订单明细.折扣率)- 零件供应.成本价 * 订单明细.订购数量 as 利润
	from
		订单明细
	join 订单 on 订单明细.订单ID = 订单.订单ID
	join 零件 on 订单明细.零件ID = 零件.零件ID
	join 供应商 on 订单明细.供应商ID = 供应商.供应商ID
	join 国家 on 供应商.国家ID = 国家.国家ID
	join 零件供应
	on 零件供应.零件ID = 订单明细.零件ID
		and 零件供应.供应商ID = 订单明细.供应商ID
	where
		零件.零件名称 like '%轴%'
	) as 利润表
group by
	国家名称,
	年份
order by
	国家名称,
	年份 desc;

SQLazy 写法

复制代码
订单明细:导出表 零件ID, 供应商ID, 订购金额, 折扣率, 订购数量, 订单ID.订单日期, 零件ID.零件名称, 供应商ID.国家ID.国家名称
拼接 零件ID 供应商ID 关联表 零件供应 零件ID 供应商ID 拼接列 成本价 内连接
筛选 (零件名称 串匹配 "%轴%")
计算列 year(订单日期) 命名 年份, 订购金额 * (1 - 折扣率) - 成本价 * 订购数量 命名 利润
汇总 合计 利润 命名 总利润 分组 国家名称, 年份
排序 国家名称, 年份 降序
导出表 国家名称, 年份, 总利润

六张表的 join,其中零件供应需要按零件ID和供应商ID双字段关联------SQL 里要写 on ... and ...,SQLazy 里一行「拼接 零件ID 供应商ID 关联表 零件供应 零件ID 供应商ID」就搞定。子查询被压成计算列,利润公式直接写成业务表达式,读起来就是一句话:取数 → 补成本价 → 筛轴类零件 → 算利润 → 按国家和年份汇总。

4.6 TPC-H Q21:exists 与 not exists 交织,找出发货延迟的供应商

SQL 写法

复制代码
select
	供应商.供应商名称,
	count(*) as 等待次数
from
	订单明细 as 明细1
join 订单 on 明细1.订单ID = 订单.订单ID
join 供应商 on 明细1.供应商ID = 供应商.供应商ID
join 国家 on 供应商.国家ID = 国家.国家ID
where
	订单.订单状态 = 'F'
	and 明细1.实际到货日期 > 明细1.承诺到货日期
	and exists (
		select 1
		from 订单明细 as 明细2
		where
			明细2.订单ID = 明细1.订单ID
			and 明细2.供应商ID <> 明细1.供应商ID
		)
	and not exists (
		select 1
		from 订单明细 as 明细3
		where
			明细3.订单ID = 明细1.订单ID
			and 明细3.供应商ID <> 明细1.供应商ID
			and 明细3.实际到货日期 > 明细3.承诺到货日期
		)
	and 国家.国家名称 = 'SAUDI ARABIA'
group by
	供应商.供应商名称
order by
	等待次数 desc,
	供应商.供应商名称;

SQLazy 写法

复制代码
明细=订单明细:导出表 订单ID, 供应商ID, 订单ID.订单状态, 供应商ID.供应商名称, 供应商ID.国家ID.国家名称, 实际到货日期, 承诺到货日期
延迟明细=筛选 (订单状态 = "F" 且 实际到货日期 > 承诺到货日期)
明细:汇总 唯一计数 供应商ID 命名 供应商数 分组 订单ID
多供应商订单=筛选 (供应商数 > 1)
延迟明细:汇总 唯一计数 供应商ID 命名 延迟供应商数 分组 订单ID
唯一延迟供应商订单=筛选 (延迟供应商数 = 1)
候选订单=多供应商订单:匹配 关联表 唯一延迟供应商订单
延迟明细:匹配 关联表 候选订单 
筛选 (国家名称 = "SAUDI ARABIA")
汇总 计数 订单ID 命名 等待次数 分组 供应商名称
排序 等待次数 降序, 供应商名称
导出表 供应商名称, 等待次数

exists 和 not exists 交织在一起,SQL 里要自关联三次(明细1、明细2、明细3),读的人得拿着笔顺藤摸瓜。SQLazy 版本是一条从上到下的流水线:先筛出延迟交货的明细 → 找出多供应商订单 → 从中筛出只有一个供应商延迟的订单 → 匹配回来 → 按沙特供应商汇总等待次数。每一步都是一个中间变量,命名即注释,没有任何嵌套。

4.7 30 天滑动窗口汇总:区间引用取代窗口帧

需求:对订单数据按订单日期排序,以天为单位汇总。以滑动窗口方式统计:从第一条记录开始,每天作为一个窗口的结束时间,每个窗口包含当天及其前 29 天(共 30 天)内的订单数据,统计每个窗口的订单总数和订单总金额,窗口之间滑动步长为 1 天,只输出时间跨度大于 29 天的窗口。

SQL 里的难点:需要用 rows between 窗口帧来定义滑动范围,窗口函数的帧定义语法复杂,且不同数据库的窗口函数方言差异大。

SQLazy 写法

复制代码
订单:汇总 计数 订单ID 命名 每日订单数,合计 订单金额 命名 每日订单金额 分组 订单日期
计算列 合计 每日订单数[-29:0] 命名 订单总数; 合计 每日订单金额[-29:0] 命名 订单总金额; 计数 每日订单数[-29:0] 命名 窗口天数
筛选 窗口天数 >= 30
导出表 订单日期 命名 窗口结束日期,订单总数,订单总金额

rows between 29 preceding and current row 这样的窗口帧定义,在 SQLazy 里变成了每日订单数-29:0------区间引用,字面可读。-29:0 表示从当前行往前取 29 行到当前行,共 30 天的数据。不需要理解窗口帧的语法,下标就是它的字面意思。

4.8 各国账户余额前三名:排名之后外键依然可用

SQL 写法

复制代码
select 国家名称, 客户名称, 客户账户余额
from (
	select c.客户ID, c.客户名称, c.客户账户余额, n.国家名称,
	row_number() over (partition by c.国家ID order by c.客户账户余额 desc) as rn
	from 客户 c
	join 国家 n on c.国家ID = n.国家ID
	) t
where rn <= 3

SQLazy 写法

复制代码
客户:排名 客户账户余额 降序 前 3 分区 国家ID
导出表 追加 国家ID.国家名称 命名 国家名称

row_number()over (partition by ... order by ...) 套一层子查询,在 SQLazy 里变成一行「排名 客户账户余额 降序 前 3 分区 国家ID」。更关键的是第二步:排名结果上的国家ID仍然「认得」国家表,直接用「.」把国家名称补上即可------不需要为了拿一个国家名称,把国家表提前 join 进排名的输入里。主键和外键关系在排名之后依然保持,这就是链路继承带来的省事。

4.9 年同比 + 季环比:下标引用取代自关联

需求:统计每个零件在各年份的销售情况,计算每个零件的年度同比销售额(与上一年度对比)和季度环比销售额(与上一季度对比),并计算对应的增长率百分比。

SQL 里的难点:同一张订单明细表既要按年汇总又要按季汇总,两次汇总结果之间要自关联拼接,才能把上年销售额和上季销售额带回同一行。自关联的 join 条件还要处理年份差和季度差的逻辑,代码冗长且易错。

SQLazy 写法

复制代码
订单明细:导出表 订单ID, 零件ID, 订购金额, 订单ID.订单日期, 零件ID.零件名称
销售=计算列 year(订单日期) 命名 年, quarter(订单日期) 命名 季
汇总 合计 订购金额 命名 年销售额, 零件名称 命名 零件名称 分组 零件ID, 年
排序 零件ID, 年
年同比=计算列 条件((年[-1] 非空) 且 ((年 - 年[-1]) = 1) 则 年销售额[-1] 否则 空) 命名 上年销售额, 条件((年[-1] 非空) 且 ((年 - 年[-1]) = 1) 则 round((年销售额/年销售额[-1] - 1) * 100, 2) 否则 空) 命名 同比增长率百分比 分区 零件ID
销售:汇总 合计 订购金额 命名 季销售额, 零件名称 命名 零件名称 分组 零件ID, 年, 季
排序 零件ID, 年, 季
计算列 条件((年[-1] 非空) 且 (((年 - 年[-1]) * 4 + (季 - 季[-1])) = 1) 则 季销售额[-1] 否则 空) 命名 上季销售额, 条件((年[-1] 非空) 且 (((年 - 年[-1]) * 4 + (季 - 季[-1])) = 1) 则 round((季销售额/季销售额[-1] - 1) * 100, 2) 否则 空) 命名 季度环比增长率百分比 分区 零件ID
拼接 零件ID 年 关联表 年同比 零件ID 年 拼接列 年销售额, 上年销售额, 同比增长率百分比
排序 零件ID, 年, 季
导出表 零件ID, 零件名称, 年, 季, 季销售额, 上季销售额, 季度环比增长率百分比, 年销售额, 上年销售额, 同比增长率百分比

SQL 里要反复自关联同一张表来把上期值带到当前行,年与年之间、季与季之间的衔接还要判断年份差和季度差。SQLazy 用年销售额-1取上一行(即上一年的销售额),用分区 零件ID保证只在同一个零件内部取上期值,再用拼接把年同比结果带回季度明细------语序即逻辑,不需要在脑子里先画一遍 join 关系图。

五、写在最后

回到开头的问题:学 SQL 到底难在哪?难在它要求你先把业务想法翻译成机器的叙述方式------join 的顺序、子查询的嵌套、窗口帧的定义,都是翻译过程里的损耗和出错点。

SQLazy 把这层翻译工作接了过来:你用业务语言描述计算过程,它负责编译成标准 SQL 在数据库执行。而 TRAE + SQLazy MCP 又把写这一步也接了过去:你说需求,AI 生成 SQLazy 脚本、自动造测试数据、自动验证结果,连存量 SQL 都能一键倒译回来。

三层简化叠加之后,做一次数据查询的路径变成了:打开 TRAE → 说一句话 → **打开生成的脚本看结果。**整个过程里,SQL 只出现在两个地方:编译按钮按下去之后,和翻译比对通过之后------它仍在为数据库服务,只是不再需要你先学会它。

哪怕你昨天才第一次打开 SQLazy,今天也可以让 AI 替你写下第一段查询。这就是这套工具链想带来的东西:更短、更清楚、更容易上手------让代码说业务的话,让 AI 替你写代码。

说明:文中示例基于 SQLazy 内存库示例数据(客户、订单、订单明细、零件、零件供应、供应商、国家、地区),表结构与主外键均取自实际内存表定义; SQL 侧示例用于对照语义,部分为节选。

相关推荐
ly76892 小时前
PostgreSQL 执行计划深读:从 EXPLAIN 输出到代价模型驱动的 SQL 改写
数据库·sql·postgresql·explain·执行计划·代价模型
川石课堂软件测试3 小时前
涨薪技术|0到1学会性能测试第8课-Analysis分析图
服务器·数据库·python·sql·jmeter·mysql·容器
我命由我123453 小时前
SQL 检测脚本
java·数据库·sql·功能测试·单元测试·压力测试·可用性测试
我的愿望是成为富婆5 小时前
2027校招|大数据管理与应用专业:从会用技术工具到解决业务问题
sql
鸽芷咕5 小时前
把 SQL 编辑器用顺:KSQL Developer 从补全到事务的实战笔记
笔记·sql·编辑器
呆萌很5 小时前
DISTINCT 和 GROUP BY 核心区别
数据库·sql
ProcessOn1 天前
纯干货!MySql实战02:一条SQL更新语句执行流程大探索!
sql·mysql·sql server
geovindu1 天前
sql: JSON and XML Data Handling in SQL using mysql 9.0
数据库·sql·mysql·数据库开发
泡海椒1 天前
JQuick-SQL SELECT 投影:字段、别名与表达式查询
数据库·sql