首页/新闻资讯/正文详情

LeetCode 1205 每月交易 II:用 SQL union 与 join 拆解 Transactions 统计口径

发布时间:2026/9/26 17:20:24 来源:云帆数科 栏目:资讯中心
LeetCode 1205 每月交易 II:用 SQL union 与 join 拆解 Transactions 统计口径
1. 为什么 1205 每月交易 II 用 join 会卡住LeetCode 1205 每月交易 II 是一道典型的 SQL 统计口径题核心考点是 union 与 join 的配合使用。题目给了两张表Transactions 记录每笔交易的国家、状态approved / declined、金额和日期Chargebacks 记录退单信息通过 trans_id 关联到 Transactions 的 id。要求输出每个国家每个月的已批准交易数量与总金额、退单数量与总金额并且忽略所有为零的行。很多人第一反应是用 join 把两张表拼起来然后按月份和国家分组。问题在于Transactions 里同一笔交易可能既有 approved 状态又有对应的退单记录join 之后行数会膨胀approved_count 和 chargeback_count 的统计口径就混在一起了。更麻烦的是退单的月份取自 Chargebacks.trans_date而正常交易的月份取自 Transactions.trans_date两者可能落在不同月份用 join 对齐月份时逻辑会变得非常绕。我试过直接用 join 写结果 approved_count 怎么算都不对因为退单行会把 approved 的计数带偏。正确的思路是先把两类事件「拉平」成同一张宽表再统一聚合。这就是 union all 的用武之地把 approved 交易和退单分别投影成相同列数的结果集用 0 占位补齐缺失的指标最后在外层用 sum if 做条件聚合。这道题适合已经掌握基础 group by 和聚合函数、想进阶理解「事件流合并」思路的 SQL 学习者。下面我会给出可复制的建表语句、样例数据、完整 SQL 骨架以及逐步验证结果的动作你可以直接在本地 MySQL 或在线 SQL 环境里跑一遍。2. TaoToken 前置用模型对话快速验证 SQL 逻辑写这类题时最容易出错的不是语法而是统计口径的理解。比如「退单数量」到底按退单日期所在月算还是按原交易日期所在月算题目明确说退单的月份取自 Chargebacks.trans_date这一点如果理解偏了整个查询就废了。在动手写之前我习惯先用模型对话把口径确认一遍。TaoToken 的模型对话入口可以帮你把题目描述翻译成清晰的字段映射关系比如「approved_count 对应 Transactions 中 stateapproved 的行数」「chargeback_count 对应 Chargebacks 中每个 trans_id 一行」这样写 SQL 时心里有底。如果你打算长期刷 LeetCode 数据库题或者需要频繁调试 SQL可以考虑 Coding Plan它更适合这种需要反复对话、逐步推导的场景。接入方式也很简单拿到 API Key 后按文档配置即可。具体入口模型对话https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel_chatCoding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding_planAPI Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi_keys接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdocAPI 地址是 https://taotoken.net/api注意这个不带 UTM 参数。官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。需要说明的是TaoToken 在这里的角色是辅助你理清思路、验证 SQL 片段的工具不是替代你写代码。真正的解题逻辑还是得自己推一遍尤其是 union 的列对齐和 if 条件聚合这两步。3. 可复制配置建表、样例数据与完整 SQL 骨架先把环境搭起来。以下建表语句和样例数据可以直接在 MySQL 里执行字段类型和题目描述一致。Create table If Not Exists Transactions ( id int, country varchar(4), state enum(approved, declined), amount int, trans_date date ); Create table If Not Exists Chargebacks ( trans_id int, trans_date date ); Truncate table Transactions; insert into Transactions (id, country, state, amount, trans_date) values (101, US, approved, 1000, 2019-05-18), (102, US, declined, 2000, 2019-05-19), (103, US, approved, 3000, 2019-06-10), (104, US, declined, 4000, 2019-06-13), (105, US, approved, 5000, 2019-06-15); Truncate table Chargebacks; insert into Chargebacks (trans_id, trans_date) values (102, 2019-05-29), (101, 2019-06-30), (105, 2019-09-18);数据准备好后先看第一步把两类事件 union 成同一张宽表。注意 union all 要求上下两部分的列数和类型一致所以 approved 部分用 0 占位 chargeback_count退单部分用 0 占位 approved_count。select left(trans_date, 7) as month, country, amount as approved_count, 0 as chargeback_count from Transactions where state approved union all select left(c.trans_date, 7) as month, t.country, 0 as approved_count, t.amount as chargeback_count from Chargebacks c left join Transactions t on c.trans_id t.id;这里有个细节退单部分需要从 Transactions 里取 country因为 Chargebacks 表本身没有国家字段。用 left join 关联后t.country 就是原交易的国家。注意退单对应的原交易可能是 declined 状态比如 trans_id102但题目要求退单也要统计所以这里不能加 state 过滤。跑完这一步你会看到 5 行结果3 行 approved101、103、1052 行 chargeback102、101、105 中实际有 3 条退单但 102 对应的原交易是 declined仍然算退单。等等样例数据里 Chargebacks 有 3 条记录102、101、105。所以 union 后应该是 3 3 6 行。其中 101 和 105 既有 approved 又有 chargeback会分别出现在两个部分里。接下来是外层聚合。用 CTE 把 union 结果包起来然后按 month 和 country 分组用 sum(if(...)) 做条件计数和求和。with tmp as ( select left(trans_date, 7) as month, country, amount as approved_count, 0 as chargeback_count from Transactions where state approved union all select left(c.trans_date, 7) as month, t.country, 0 as approved_count, t.amount as chargeback_count from Chargebacks c left join Transactions t on c.trans_id t.id ) select month, country, sum(if(approved_count 0, 1, 0)) as approved_count, sum(approved_count) as approved_amount, sum(if(chargeback_count 0, 1, 0)) as chargeback_count, sum(chargeback_count) as chargeback_amount from tmp group by month, country;这里的关键是 if 条件approved_count 0 时计 1否则计 0这样就能把占位的 0 排除掉。同理 chargeback_count。金额直接 sum 即可因为占位的 0 不影响求和。4. 验证请求与成功结果把上面的完整 SQL 贴到 LeetCode 的编辑器里提交或者本地跑一遍预期输出如下monthcountryapproved_countapproved_amountchargeback_countchargeback_amount2019-05US11000120002019-06US28000110002019-09US0015000逐行核对一下2019-05approved 只有 1011000chargeback 有 1022000原交易 declined 但退单仍算。所以 approved_count1approved_amount1000chargeback_count1chargeback_amount2000。2019-06approved 有 1033000和 1055000合计 2 笔 8000chargeback 有 1011000退单日期 2019-06-30。所以 approved_count2approved_amount8000chargeback_count1chargeback_amount1000。2019-09没有 approvedchargeback 有 1055000退单日期 2019-09-18。approved_count0approved_amount0chargeback_count1chargeback_amount5000。注意题目说「忽略所有为零的行」这里 2019-09 的 approved_count 和 approved_amount 都是 0但 chargeback 不为零所以整行保留。如果某个月份和国家两个指标都为零才会被过滤掉。上面的查询没有显式过滤但因为 union 只产生了有事件的行所以不会出现全零行。如果你想更严谨可以在外层加一个 having 条件having approved_count 0 or chargeback_count 0不过对于这道题的样例数据不加也能过。5. 本篇常见错排查5.1 union 列数不匹配导致报错最常见的错误是 union 两边列数不一致。比如 approved 部分写了 4 列退单部分只写了 3 列MySQL 会直接报「The used SELECT statements have a different number of columns」。解决方法是确保两边都是 month、country、approved_count、chargeback_count 四列缺的用 0 或 null 占位。5.2 退单部分忘记关联 countryChargebacks 表只有 trans_id 和 trans_date没有 country。如果直接 select country 会报字段不存在。必须 left join Transactions 才能拿到国家。这里用 left join 而不是 inner join是因为退单对应的原交易一定存在题目说 trans_id 是外键但用 left join 更保险。5.3 if 条件写反导致计数错误有人写成 sum(if(approved_count 0, approved_count, 0))这样得到的是金额而不是数量。计数应该用 1 和 0求和用原值。另外注意 approved_count 这个别名在 union 的第一部分里其实是 amount命名容易混淆建议在 CTE 里改成 approved_amount 和 chargeback_amount 更清晰。5.4 月份提取方式不兼容left(trans_date, 7) 在 MySQL 里能用因为 date 类型转字符串后是 YYYY-MM-DD 格式。但在其他数据库如 PostgreSQL里可能需要 to_char(trans_date, YYYY-MM)。LeetCode 的 MySQL 环境用 left 没问题但如果你本地是其他数据库记得换函数。5.5 忽略零行的理解偏差题目说「忽略所有为零的行」指的是 approved_count、approved_amount、chargeback_count、chargeback_amount 四个指标全为零的行。如果只有 approved 为零但 chargeback 不为零这行要保留。上面的查询因为 union 只产生有事件的行天然不会出现全零行所以不用额外过滤。6. 继续刷题与调试的建议这道题的核心思路可以迁移到很多「多事件流合并统计」的场景比如订单表和退款表合并统计、日志表和异常表合并统计。union all 负责拉平结构join 负责补齐维度外层聚合负责条件计数这个套路值得记下来。如果你在写 SQL 时经常卡在口径理解上可以试试用模型对话把题目拆成字段映射表再动手写。需要长期调试的话Coding Plan 的对话式交互会更顺手。API Key 在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi_keys 获取接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc。最后留一个小练习如果把题目改成「退单月份按原交易月份算」SQL 该怎么改提示退单部分的 month 改成 left(t.trans_date, 7) 即可。你可以自己跑一遍对比结果看看差异在哪里。

相关推荐

基于STM32的智能鸽舍硬件系统设计与工程实践
基于STM32的智能鸽舍硬件系统设计与工程实践

1. 这不是玩具,是真正能落地的鸽舍智能管家我第一次在华北某信鸽协会看到这套系统时,它正稳稳运行在32只赛鸽的混合鸽舍里——温度传感器实时监测着巢箱微环境,喂食器按预设节律精准投料,红外计数模块默默记录每只鸽子进出次数&am… · 2026/9/26 17:20:24

QEMU模拟器实战:嵌入式开发如何摆脱等硬件的困境
QEMU模拟器实战:嵌入式开发如何摆脱等硬件的困境

上个月我把一块新拿到的开发板给烧了。烧完那一刻我反而松了口气——这块板子从下单到我手里用了九天,结果我碰了一个引脚,一周没了。这正是我后来花时间把QEMU这类仿真工具捡起来的原因:嵌入式开发最大的成本往往不是智商,不是技… · 2026/9/26 17:20:24

Julia复现电网经济调度与频率控制分层耦合模型全记录
Julia复现电网经济调度与频率控制分层耦合模型全记录

电网调度和频率控制,在我刚入行那几年一直被当成两个“战壕”里的工作:做经济调度的人天天盯机组负荷率、煤耗曲线、启停顺序,追求的是每一度电发得够便宜;做频率控制的人则盯着AGC、一次调频死区、系统惯量,追求的是电… · 2026/9/26 17:20:18

2026企业级AI编程平台选型指南:TaoToken统一Key接入与私有化部署评估
2026企业级AI编程平台选型指南:TaoToken统一Key接入与私有化部署评估

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 17:48:20

电梯维保毕设不卡壳:我会这样搭配 AI 写作工具 [特殊字符]
电梯维保毕设不卡壳:我会这样搭配 AI 写作工具 [特殊字符]

先把场景说具体:电梯工程技术专业的毕业任务,很常见的一类是**“某小区曳引式电梯故障统计分析与维保方案优化”**。 你在实习物业或维保单位可能拿到一批报修记录,比如门系统故障、制动器异常、平层不准、控制柜报警、乘客操作不当等。最后… · 2026/9/26 17:48:20

吉林大学虚拟现实游戏程序设计作业:Unity VR开发从零到可运行Demo完整指南
吉林大学虚拟现实游戏程序设计作业:Unity VR开发从零到可运行Demo完整指南

简介:这份资源是吉林大学虚拟现实游戏程序设计课程的射击类游戏作业完整工程,面向正在学习Unity与VR开发的高校学生及自学者,可帮助读者对照课程要求完成第一人称或第三人称射击游戏的策划与实现。压缩包共约2000个文件,整体231.9… · 2026/9/26 17:48:20

LLVM ADT与内存管理机制解析及大模型推理显存优化对照
LLVM ADT与内存管理机制解析及大模型推理显存优化对照

LLVM 这套东西,很多人第一次接触都是从"我想写个编译器"或者"我想看懂某个报错"开始的,结果一头扎进去发现 ADT(抽象数据类型)和内存管理这两块比想象中要绕得多。我自己前前后后翻过几遍 LLVM 的源码&#x… · 2026/9/26 17:48:20

MCP协议落地实战:OpenClaw与OpenOcta部署避坑指南
MCP协议落地实战:OpenClaw与OpenOcta部署避坑指南

1. 这不是“替代品测评”,而是一场开发者工作流的底层重构最近在几个技术社区里,总能看到有人问:“有没有 Workbuddy 的开源平替?”——但这个问题本身就有陷阱。Workbuddy 不是一个能被简单“替换”的软件,它本质是一… · 2026/9/26 17:48:13

代码评审、智能体ECC与文本去AI味:本周开源项目实战解析
代码评审、智能体ECC与文本去AI味:本周开源项目实战解析

这周的周刊我在选题时来回删了好几版,最后留下的四个方向分别是:代码评审、ADHD友好输出、智能体运行底座ECC、文本去AI味。前两个属于“把工具做得更好用”,后两个属于“把AI真正当工程做”。刚好对应了当下GitHub社区两条明显的热度线&… · 2026/9/26 17:48:13

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码