我一直在跟 n8n 工作流打交道,有个感受特别深:数据聚合这件事,几乎每个自动化里都会撞上。你从三个平台拉了订单数据,要汇总成一张月度营收表;你从报名系统导出了两千条记录,想按城市统计人数;你跑了十几次 API,最后要把所有结果归拢成一个总览。这些需求看着五花八门,本质都是同一件事——把分散的行级数据,压缩成一组有信息密度的汇总值。n8n 里专门干这事的节点就是 Summarize,很多人叫它“数据聚合的魔法武器”,真不是夸张。
这篇教程我会把 Summarize 的原理、参数、实操流程和踩坑经验一次性讲透。适合正在用 n8n 做报表自动化、数据清洗、接口对接的人看,也适合刚接触 n8n、被各种节点搞得一头雾水的新手。你看完以后,至少能分清“分组字段”和“聚合规则”的关系,遇到空值、类型错误、顺序不固定这类问题也知道先查哪里。
1. 为什么说 Summarize 是数据聚合的魔法武器
1.1 没有 Summarize 之前,数据聚合有多痛
我先讲个场景。之前帮朋友做一个小型电商的运营数据汇总,每天要统计各区域销售额、订单数、客单价、销售人数。数据源头是几个不同的接口,有的是订单列表,有的是客户跟进记录,字段还不统一。最开始我是打算写一个 Function 节点,用一堆 JavaScript 代码去循环遍历、做 MapReduce 式的归约。写出来大概五十多行,跑是能跑,但问题来了:业务方说“区域口径要改成按省分组”,改代码;又说“要再加一个最大单笔金额”,还得改代码。每次改动都在跟正则、多维数组较劲,试错成本非常高。
后来换了个思路,用数据库 SQL 做。但对于纯接口数据,你不可能先把所有数据灌进 MySQL 再去查,而且临时建表、维护 Schema 也是一堆事。Excel 透视表倒是能做,可它停留在人工操作层面,没法塞进自动化流程里每天自动跑。
这就是问题所在:大量真实业务数据不落在数据库里,而是流动在 API、表单、消息队列、Excel 导入这些环节中。我们需要一个能直接放在流程中间、可视化配置、改需求不伤筋动骨的数据聚合工具。n8n 的 Summarize 节点就是专门解决这个场景的。
1.2 为什么是 Summarize 而不是别的方案
拿一张表对比看会更直观:
| 方案 | 灵活度 | 自动化能力 | 维护成本 | 适合场景 |
|---|---|---|---|---|
| Excel/透视表 | 高 | 低 | 中 | 一次性人工分析 |
| Python/pandas 脚本 | 高 | 中 | 高 | 复杂建模、灵活分析 |
| SQL GROUP BY | 高 | 中 | 中 | 数据已落在数据库 |
| n8n Summarize 节点 | 中高 | 高 | 低 | 自动化流程中的实时聚合 |
这里要说清楚一个底层逻辑:Summarize 本质上就是一种归约(Reduce)操作。你输入一系列条目,它按照你指定的维度分组,对每一组执行求和、平均、计数、拼接等计算,最后输出的是组级汇总条目。这个模型和 SQL 的GROUP BY非常像,但因为它在 n8n 流程里运行,输入来源可以是你前面任何节点拉到的数据,输出也能直接喂给后面任何节点,这就把“取数、清洗、聚合、分发”串成了一条完整的自动化链路。
为什么我会说它像魔法武器?因为它把原本需要写代码的归约逻辑,压缩成了一个可视化配置界面。只要你理解“分组维度”和“度量值”这两个概念,日常 80% 的聚合需求都能在这一个节点里解决,而且改字段就像改 Excel 表头一样简单,不用碰代码。
2. 核心概念与配置项解析
2.1 四个关键配置项,搞懂它们你就能上手
打开 Summarize 节点,你会看到界面里主要就是两块:左边是聚合规则列表(Aggregation),右边是分组字段选择(Fields to Split By,部分旧版本里也叫 Group by)。不同 n8n 版本的界面措辞会有点差别,但核心逻辑一致。
先说聚合规则。这个列表允许你添加多条规则,每一条规则通常由三部分组成:选择聚合方式、选择要计算的字段、自定义输出字段名。比如我想统计“各区域的总销售额”,聚合方式选Sum,字段选amount,输出字段名写成total_amount。
再说分组字段。这个字段决定数据按哪个维度被切分,对应 SQL 里的GROUP BY。如果你选择customer_region,那么所有华东的订单会被归到一起,华南的订单归到一起,最后每个区域输出一行汇总数据。如果你同时选择多个分组字段,就相当于多维度分组,比如“区域 + 销售渠道”,输出也会变成按复合维度展开的多行。
这里有个很多人忽略的点:聚合规则是复数概念,可以同时存在多条。也就是说,你可以在同一个节点里既算总和、又算平均数、又算最大单笔金额。多条规则共享同一套分组逻辑,最后会作为不同的字段输出在同一行里。这种“一套分组、多组度量”的设计,其实就是数据库 OLAP 和透视表的核心理念,用起来非常顺手。
2.2 聚合方式逐个拆解,选对才是关键
Summarize 节点支持的聚合方式不少,我用一个销售订单的例子逐个解释,这样你理解起来最省力。
| 聚合方式 | 作用 | 业务示例 |
|---|---|---|
| Sum | 求和 | 按区域汇总销售额 |
| Average | 平均值 | 计算客单价 |
| Median | 中位数 | 算日常销售额的稳健水平,不受大额订单影响 |
| Min | 最小值 | 找最低订单金额 |
| Max | 最大值 | 找最大单笔订单 |
| Count | 计数 | 统计订单总笔数 |
| Count Unique | 去重计数 | 统计去重后的客户数 |
| Append | 追加为数组 | 把所有订单号装进一个数组 |
| Concatenate | 拼接为字符串 | 把销售名字拼成“张三、李四” |
| Remove Duplicates | 去重 | 去掉重复项后输出 |
| Latest | 取最新 | 获取分组内最新一条记录 |
| Earliest | 取最早 | 获取分组内最早一条记录 |
说几个实际使用中的心得。Sum、Average、Count是最常用的三件套,但很多人会把Count和Count Unique用混。Count统计的是分组内的行数,哪怕这个字段里的值是空的,行数也会算进去;Count Unique则是按某个字段去重后再计数,比如统计“有订单的客户数”,就得对客户 ID 做去重计数,而不是单纯数订单行。
Median这个选项用得少,但遇到分布特别不均匀的数据时非常好用。比如店铺里有几笔大额批发订单,平均客单价被拉得很高,这时候看中位数更能反映普通顾客的真实消费水平。Append和Concatenate则适合保留明细,比如你把几十个订单号先拼成一个数组,下游再用循环节点逐个处理,比直接丢一堆原始数据过去更清爽。
2.3 类型与空值的底层逻辑,数据不干净先别聚合
这里要单独说一个底层细节:n8n 内部的数据类型感知。所有字段本质上都是 JavaScript 的类型体系,number和string是两回事。当你从 HTTP 接口或者 Excel 导入拿数据时,经常会出现金额字段以字符串形式存在的情况,比如"1200"而不是1200。如果你直接把这个字段交给Sum,n8n 可能直接报类型错误,或者把结果算成 0,这类问题排查起来很隐蔽。
所以一个很重要的实践原则:聚合之前,数据清洗先行。我通常会在 Summarize 前面挂一个 Edit Fields 节点(旧版本叫 Set 节点),把参与计算的数值字段显式转换为数字类型,把需要分组的字段做去除首尾空格、统一大小写的处理。最常用的表达式就是{{ Number($json.amount) }},或者直接在字段类型下拉框里选择 Number。
空值问题同样要提前处理。假如分组字段里有空值,这个分组会被单独归成一个null分组,输出结果就会出现一行customer_region: null的数据。如果聚合字段有空值,Sum的结果也可能不符合预期。我的建议是:在聚合前用 Filter 节点把关键字段为空的行过滤掉。让 Summarize 只管归约计算,不承担清洗职责,这样每个节点单干一件事,流程思路会清晰很多。
3. 实操:用 Summarize 完成一次完整的销售数据聚合
3.1 场景设定与数据准备
我们来做一次完整实操。假设你在运营一个小型电商系统,需要每天把某接口返回的订单列表,按照客户区域汇总销售额、订单数、客单价和去重后的销售人数。这是很典型的一个运营日报需求。
首先,用 HTTP Request 节点拉取订单数据,或者为了方便测试,用一个 Edit Fields 节点模拟一批静态数据。订单接口返回的数据大概长这样:
[ { "order_id": "A001", "customer_region": "华东", "sales_person": "李雷", "amount": 1200, "payment_status": "paid" }, { "order_id": "A002", "customer_region": "华南", "sales_person": "韩梅梅", "amount": 800, "payment_status": "paid" }, { "order_id": "A003", "customer_region": "华东", "sales_person": "李雷", "amount": 2400, "payment_status": "paid" } ]注意这里amount字段必须是数字类型,如果接口返回的是带引号的字符串,先在前面用 Edit Fields 转换好。这是整个实操里最容易翻车的一点。
3.2 单字段分组聚合,一键生成区域汇总
第一步,先做一个最基础的需求:按客户区域汇总销售额。在 Summarize 节点中,聚合规则列表添加一条规则:
- 聚合方式:
Sum - 字段:
amount - 输出字段名:
total_amount
然后在 Fields to Split By 中选择customer_region。保存运行后,你会看到输出变成了三行左右的汇总数据:
[ { "customer_region": "华东", "total_amount": 3600 }, { "customer_region": "华南", "total_amount": 800 } ]这行数据等价于 SQL 里的SELECT customer_region, SUM(amount) FROM orders GROUP BY customer_region。如果你懂 SQL,看到这里基本就通了。稍微提一句:n8n 的界面里所有字段都是英文,你最好也把输出字段名定义成清晰的小写英文加下划线,后面被其他节点引用时不容易出错。
3.3 多条聚合规则同时生效,一表打尽所有指标
接下来我们升级一下需求:同一个区域维度下,既要总销售额,又要订单笔数,又要客单价,还要去重后的销售人员数。直接在 Aggregation 列表里添加多条规则就行:
| 聚合方式 | 目标字段 | 输出字段名 | 含义 |
|---|---|---|---|
| Sum | amount | total_amount | 区域总销售额 |
| Count | order_id | order_count | 订单数 |
| Average | amount | avg_amount | 平均客单价 |
| Count Unique | sales_person | sales_count | 去重销售人数 |
| Max | amount | max_amount | 单笔最大金额 |
运行后,每一个区域会输出一行包含所有指标的数据:
[ { "customer_region": "华东", "total_amount": 3600, "order_count": 2, "avg_amount": 1800, "sales_count": 1, "max_amount": 2400 } ]这种写法很像透视表里把多个“值字段”同时拖到数值区域,很好用。尤其推荐这种“一个维度列,多列度量值”的输出结构,因为下游无论是转成表格、发邮件还是写入数据库,都是最标准、最好处理的宽表结构。很多人习惯把聚合结果做成嵌套结构,反而给下游增加了不少解析成本。
3.4 聚合结果不排序?接一个 Sort 节点就好了
有个细节很多人实操才会发现:Summarize 节点输出的分组顺序是不固定的,它取决于输入顺序和内部实现,不一定按业务想要的方式排。比如你想让销售额最高的区域排在最前面,就必须在 Summarize 后面再接一个 Sort 节点。
Sort 节点配置也简单:排序字段选择total_amount,排序方向选择Descending(降序)。这样输出就变成了华东、华南这种从高到低的排列。
完整的流程串联起来就是:HTTP Request 拉订单数据 → Edit Fields 清洗类型 → Summarize 按区域聚合 → Sort 按销售额降序排列 → 最终输出给报表或通知节点。这个链路基本覆盖了你做自动化报表的绝大多数场景。你可以把最终数据接上 Spreadsheet 节点生成 CSV 文件,也可以接 Send Email 节点把结果发到邮箱,或者直接写入数据库做后续分析。
4. 常见问题与排查技巧实录
4.1 求和结果变成字符串,或者直接报 Invalid Number
这是最常遇到的问题。现象是 Sum 之后的结果不对,要么是 0,要么报错说字段不是数字。原因通常很简单:上游字段是字符串类型,或者值里带了货币符号,比如"$1200"这种。
解决办法就是在聚合前用 Edit Fields 节点把参与计算的字段转成 Number 类型。可以直接在字段类型下拉里选 Number,也可以用表达式{{ Number($json.amount) }}。如果值里面带符号,需要先用表达式把符号去掉再转类型,比如{{ Number($json.amount.replace(/[^0-9.]/g, '')) }}。养成这个习惯后,你会少踩一半的坑。
4.2 Count 结果看着不对,空记录也算进去了
有人统计订单数时用 Count 对order_id计数,结果发现比实际订单行数多了几条,仔细一查是存在order_id为空的脏数据。Count 的规则就是数行,它会老老实实把空行也算进去。
如果你要统计“有有效订单编号的订单数”,两个思路:一种是在聚合前用 Filter 节点过滤掉order_id为空的行;另一种是根据业务想要的口径,考虑用 Count Unique 按另一个唯一键去重。关键是先想清楚业务上到底要数“行数”还是“有效记录数”,口径不同,聚合方式也不同。
4.3 分组字段在下拉列表里找不到?多半是嵌套数据
从 API 接口拿回来的数据经常是嵌套结构,比如 JSON 长这样:{ "data": { "region": "华东" } }。这种情况下,Summarize 的字段选择面板里可能显示不出data.region这种嵌套路径,导致你选不到想分组的字段。
解决思路是提前把结构摊平。在 Summarize 前面加一个 Edit Fields 节点,用表达式{{ $json.data.region }}把它提取成顶层字段,或者用 JSON Extract 节点做字段抽取。我个人更推荐提前摊平,因为字段面板在选择顶层字段时最顺手,后续其他节点引用也更方便。
4.4 分组数据出现重复行?先检查空格和大小写
有时候你会发现华东的数据被拆成了好几行,往下拉一看,有的行是"华东",有的是"华东 "(带尾随空格),还有的是"华東"(繁体)。这在人工维护的数据里非常常见。原因就是分组字段的值并不完全一致,Summarize 把它们当成了不同的组。
处理方式:聚合前统一文本规范。用 Edit Fields 节点或者表达式对字段做trim()和toLowerCase()处理,比如{{ $json.customer_region.trim().toLowerCase() }}。这也是为什么我一直强调聚合前必须接清洗步骤,字段不规范直接聚合,结果一定让你闹心。
4.5 拼接出来的字符串把下游搞乱了
用 Concatenate 把多行值拼成字符串时,默认拼接逻辑里可能会出现分隔符问题。比如你把订单 ID 拼成"A001,A002,A003",下游如果按逗号解析,恰好某个订单 ID 里面带了逗号,解析就会错位。
稳妥的替代方案是:如果下游支持数组类型,优先用 Append 聚合方式,生成一个订单 ID 数组,再让下游按数组处理。如果只能用字符串,务必换一个不会出现在数据里的分隔符,比如|或者;,并且在文档里写清楚。这个细节看着小,生产环境里能帮你省掉不少麻烦。
4.6 聚合结果太大导致执行卡顿?先做减法
还有一个容易被忽略的性能问题。如果你选的“分组字段”基数特别高,比如订单 ID,那么每个 ID 都只会对应一行,Summarize 输出和输入几乎一样多,压根没有起到聚合作用,反而白白消耗一次内存操作。更严重的是,如果你先循环拉了很多次接口再把全量数据一股脑塞给 Summarize,节点处理量会非常大,拖慢整个工作流的执行。
正确的做法是:先在下游确认好这次聚合到底需要哪些维度,在前面用 Filter 节点把无关数据过滤掉,用 Edit Fields 节点把不需要的字段剔除,尽量把数据量减到最小再进入聚合。数据量减少,聚合速度自然快,后面排序、推送也跟着顺畅。
5. 进阶玩法:聚合之后的自动化延伸
5.1 把聚合结果扔给 AI,自动生成经营洞察
n8n 现在接大模型节点很方便,Summarize 聚合后的结构化数据非常适合作为 AI 分析的输入。你可以把聚合结果先转换成一段文本或 Markdown 表格,然后传给 AI 节点,让它生成日报解读。
比如前面得到的各区域销售额汇总,你可以用表达式把它拼成一个 Markdown 表格,然后给 AI 节点提示:“这是今日各区域销售数据,请找出增速异常或需要关注的区域,并给出三条运营建议。”这样原本需要人工盯数据的活,就能每天自动产出一份带分析结论的日报,这已经是我日常在用的玩法了。
5.2 定时聚合加报表推送,运营日报不用人盯
把这个聚合流程挂上 Schedule Trigger 节点,每天上午九点自动执行,跑完以后把结果通过 Send Email 或企业微信机器人推送出去,就是一个标准的运营日报自动化。
具体做法是:Schedule Trigger 设定cron表达式,比如每天 9 点触发;然后按刚才的链路拉数据、清洗、聚合、排序;最后用 HTML 或 Markdown 把结果排版成适合阅读的格式,推到指定邮箱或者群机器人。配上异常阈值判断的话,还能在销售额低于某个数值时自动发出告警,这就不仅仅是汇总,而是带上了初步的监控能力。
5.3 多级聚合实现“先细后粗”的报表分层
某些场景下,单一层级的聚合满足不了需求。比如业务方既要看“每天每个区域的销售变化趋势”,又要看“整个月的区域汇总”,这就建议做两层聚合了。
第一层,用 Summarize 按日期 + 区域分组,得到每日各区域的明细汇总;第二层,再对第一层输出做一次 Summarize,按区域分组,计算整月汇总或者平均每日销售额。这种多级聚合的思路很像数据仓库里的上卷(Roll-up)操作,逐层把粒度变粗。你只要理解了何时该用几级聚合,业务再复杂,基本也能通过节点组合拼出想要的数据形态。
我这里想多说一句:数据聚合只是整个自动化流程中的一环,别指望一个节点把所有事情都干了。我见过不少人握着 Summarize 想把清洗、分组、判断、格式化全塞进去,结果配置越来越复杂,一调试就是半小时。真正好用的设计是拆开:清洗归清洗,聚合归聚合,排序归排序,每个节点职责单一,出问题的时候一眼就能定位。
另外,如果你和我一样经常在 n8n 里构建重复性报表,不妨把“拉数据 → 清洗 → 聚合 → 排序 → 推送”这套链路保存成一个可复用的模板,下次换数据源时只需改字段映射和接口地址,省下的时间足够你多学两个新节点。数据聚合这事,说到底就是一门“把混乱变成结构”的手艺,而 Summarize 就是那把最顺手的工具。