让AI写SQLite汇总查询:先按订单合并退款,再查金额有没有算重

AI 写出的查询能运行,结果也可能错得很整齐。订单表一行一笔订单,退款表一行一次退款;同一订单退过两次,直接连接后订单金额就会出现两遍。本篇用四笔虚构订单,在 DB Browser for SQLite 中复现这种重复,再让 AI 写出先汇总退款、后连接的查询。适合会看表格、刚开始接触 SQL 的运营和分析人员。

准备一个隔离的练习数据库

安装官方 DB Browser for SQLite桌面版,它是开源可视化 SQLite 工具,不需要数据库服务器或云账号。AI 文本工具的登录、额度和费用另按你的服务确认;本例不需要付费模型或 API。只使用本文数据,不连接业务库,不把客户记录交给 AI。金额全部用整数“分”,避免把浮点显示误差混进连接问题。

新建空数据库,命名 practice.db。若立即弹出建表对话框,可取消,在“执行 SQL(Execute SQL)”页运行下面的初始化脚本,再点击“写入更改(Write Changes)”。这段脚本只在新建练习库运行一次;它会创建两张表并写入假数据,绝不能粘到工作数据库中。

CREATE TABLE orders (
  id TEXT PRIMARY KEY,
  channel TEXT NOT NULL,
  amount_cents INTEGER NOT NULL
);
CREATE TABLE refunds (
  id TEXT PRIMARY KEY,
  order_id TEXT NOT NULL,
  amount_cents INTEGER NOT NULL
);
INSERT INTO orders VALUES
  ('A01','web',10000), ('A02','web',10000),
  ('A03','store',8000), ('A04','store',20000);
INSERT INTO refunds VALUES
  ('R01','A01',1000), ('R02','A01',500),
  ('R03','A04',20000);

第一步:把查询环境改成只读

保存并关闭练习库,在终端中按下面方式重新打开。项目 GitHub Wiki给出的 -R 参数是只读打开;这项能力在本练习里用来限制后续 AI 查询的影响,而不是仅靠提示词说“不要改数据”。

sqlitebrowser -R "practice.db"

命令里的 sqlitebrowser 要替换为你安装的程序实际可执行文件路径,数据库也可写完整路径。若提示找不到命令,先查安装位置或该程序的 --help,不要改用不认识的下载器。无法确认只读打开时,停在练习副本,不要拿正式数据继续。只读不是允许执行任意 SQL 的理由,仍应拒绝 AI 给出的写入语句、扩展加载和外部文件操作。

第二步:给 AI 表结构、样例和核对口径

请为 SQLite 写一条只读汇总查询,并解释每个中间结果一行代表什么。不要生成建表、更新、删除、附加数据库或加载扩展的语句。
目标:按 channel 统计订单数、订单金额、退款金额、净额;全部以整数“分”为单位,净额定义为本练习的订单金额减退款金额。不涉及会计收入确认。没有退款的订单也要保留;一个订单可以有多条退款。
orders(id TEXT PRIMARY KEY, channel TEXT, amount_cents INTEGER)
A01|web|10000
A02|web|10000
A03|store|8000
A04|store|20000
refunds(id TEXT PRIMARY KEY, order_id TEXT, amount_cents INTEGER)
R01|A01|1000
R02|A01|500
R03|A04|20000
请先说明直接连接明细再 SUM(orders.amount_cents) 会怎样重复计算。再用先按 order_id 汇总退款、后 LEFT JOIN 的方式给出一条 WITH ... SELECT;不要用 SUM(DISTINCT 订单金额) 掩盖重复。列名为 channel、order_count、gross_cents、refund_cents、net_cents;按 channel 排序。最后手算两行预期值,并给出验证 A02、A03 无退款仍被保留的方法。

这里故意让 A01 与 A02 的订单金额相同:用 SUM(DISTINCT amount_cents) 会把两个不同订单的同额金额合成一个,也不是正确修复。SQLite 的聚合函数文档说明 DISTINCT 去掉的是参数里的重复值,并不理解哪个业务订单应保留。

第三步:先看重复怎么发生

在新的执行 SQL 页中只放下面这条诊断查询,运行后应看到 A01 两行,分别对应 R01、R02;A02、A03 的退款编号为空。LEFT JOIN 保留未匹配订单,符合本练习要求。相关连接规则见SQLite SELECT 文档。

SELECT o.id, o.amount_cents, r.id AS refund_id
FROM orders AS o
LEFT JOIN refunds AS r ON r.order_id=o.id
ORDER BY o.id, r.id;

诊断结果共五行,却只有四个订单。若此时按渠道累加订单金额,web 会被算成 30000 分,而正确值是 20000 分。看到这个差异后,再核对 AI 的修正语句,不要只看它有没有语法错误。

第四步:运行预汇总后的查询

下面是可用来对照的完整查询。退款先在 CTE 中收敛到每个 order_id 一行,再与订单连接;无退款时用 COALESCE 视为 0。WITH 文档和COALESCE 文档可用于核对这两个写法。注意 WITH 也能接写入语句,不能只看开头就判断安全。

WITH refund_by_order AS (
  SELECT order_id, SUM(amount_cents) AS refund_cents
  FROM refunds
  GROUP BY order_id
)
SELECT o.channel,
       COUNT(*) AS order_count,
       SUM(o.amount_cents) AS gross_cents,
       SUM(COALESCE(r.refund_cents,0)) AS refund_cents,
       SUM(o.amount_cents-COALESCE(r.refund_cents,0)) AS net_cents
FROM orders AS o
LEFT JOIN refund_by_order AS r ON r.order_id=o.id
GROUP BY o.channel
ORDER BY o.channel;

将 AI 的回答和这份参考逐项比较,再把通过检查的一条查询放到新的 SQL 页执行。不要连同建表脚本一起运行。执行入口可用工具栏,也可按官方快捷键说明中的 Ctrl+Return。结果应恰好有以下两行,列中的金额单位仍是分,不要为了显示元而提前四舍五入:

channel 订单数 订单金额/分 退款/分 净额/分
store 2 28000 20000 8000
web 2 20000 1500 18500

第五步:用三道小检查验收

  • 行数:原订单是 4 行,预汇总退款只有 A01、A04 两行;连接后必须恢复为 4 行,而不是直接连接的 5 行。
  • 逐笔:A01 净额 8500,A02 为 10000,A03 为 8000,A04 为 0。A02、A03 没有退款也不能消失。
  • 总额:两渠道合计订单金额 48000、退款 21500、净额 26500 分;不要只核对某一渠道。

逐笔核对可直接运行下面这条完整查询,四笔订单都应保留。检查通过后保存正式渠道汇总查询为 summary.sql,并另外记录预期结果;保存 SQL 文件不等于保存数据库更改。

WITH refund_by_order AS (
  SELECT order_id, SUM(amount_cents) AS refund_cents
  FROM refunds
  GROUP BY order_id
)
SELECT o.id,
       o.amount_cents AS gross_cents,
       COALESCE(r.refund_cents,0) AS refund_cents,
       o.amount_cents-COALESCE(r.refund_cents,0) AS net_cents
FROM orders AS o
LEFT JOIN refund_by_order AS r ON r.order_id=o.id
ORDER BY o.id;

若金额偏大,先查连接后的订单 id 是否重复;若无退款订单消失,查是否用了 INNER JOIN 或在 WHERE 中要求退款字段非空;若仍为 NULL,查是否漏了 COALESCE;若表已存在,不要重复跑初始化,用新的空库重新练习。更多订单表还可能有币种、取消状态、退款时间等条件,不能把本题口径原封不动套进实际经营报表。把一条看起来合理的查询交付前,先写清每张表一行代表什么、关联键是否唯一、缺少匹配时保留哪一边;这些约定比让 AI 多写几句解释更能帮助别人复核。

本文已用本地 Python sqlite3 执行这些合成样例并核对数值;没有声称做过 DB Browser 图形界面实测。官方资料核对日期为 2026 年 10 月 30 日。读完项目 README 后如何决定试用边界,可参考《看见GitHub AI项目先别安装:把README读成试用决策》;这里具体落实为隔离样例、只读打开和结果复算。

© 版权声明

相关文章