SQL:如何通过WHERE子查询实现每个账户的最新指定类型事件提取
问题解决方案
原SQL核心缺陷
当前代码匹配逻辑存在两个关键问题:
- 子查询计算
MAX(event_timestamp)时没有按账户维度做关联,是全局统计所有y类型事件的最大时间,因此只会返回全局时间最新的单条记录,完全不符合"每个账户取自身最新y事件"的需求 - 冗余的
GROUP BY没有实际过滤作用,无法解决多账户的分组匹配问题
实现思路
要实现目标,必须先建立账户维度的最新事件映射关系:即对每个账户,单独计算它名下所有y类型事件的最大时间,再用这个时间去关联原表和公司表,最终拿到每个账户对应的公司名称。
可落地的实现代码
方案1:关联子查询(兼容所有SQL版本)
SELECT DISTINCT tbl1.account_id, tbl2.company_name FROM tbl1 -- 关联规则替换为你实际的SUBSTRING截取逻辑 INNER JOIN tbl2 ON tbl2.company_id = <此处填入实际的SUBSTRING(tbl1.字段, 起始位置, 长度)代码> -- 从测试样本看,y类型事件的event_value和tbl2.company_id完全匹配,如果截取规则就是取完整event_value,可直接写为 tbl2.company_id = tbl1.event_value WHERE -- 预先过滤y类型事件,减少计算范围 tbl1.event_type = 'y' -- 核心改动:和内层子查询的账户绑定,实现每个账户单独算最大时间 AND tbl1.event_timestamp = ( SELECT MAX(sub.event_timestamp) FROM tbl1 sub WHERE sub.event_type = 'y' AND sub.account_id = tbl1.account_id )
代码调整说明:相比原始SQL,仅在内层计算最大时间的子查询中增加了
sub.account_id = tbl1.account_id的关联条件,就让全局的最大时间计算变成了逐账户匹配自身最大时间的逻辑,从根源解决只返回全局单条结果的问题。
方案2:窗口函数(大表场景性能更优)
数据量较大时,窗口函数可以避免多次重复扫描同一张表,执行效率更高:
SELECT account_id, company_name FROM ( SELECT tbl1.account_id, tbl2.company_name, -- 按账户分组,将同一账户下的y事件按时间倒序排列,最新的事件标记为序号1 ROW_NUMBER() OVER ( PARTITION BY tbl1.account_id ORDER BY tbl1.event_timestamp DESC ) AS event_rank FROM tbl1 INNER JOIN tbl2 ON tbl2.company_id = <此处填入实际的SUBSTRING截取逻辑> WHERE tbl1.event_type = 'y' ) ranked_result -- 仅保留每个账户排名第1的最新事件 WHERE event_rank = 1
补充说明:如果同一账户下存在多条时间完全相同的最新y事件,可将
ROW_NUMBER()替换为RANK(),保留全部同时间的记录。
基于测试数据的预期输出
按照提供的测试样本,代码执行后会得到以下8组去重结果:
| account_id | company_name |
|---|---|
| 044ad628-7a859842851 | Company 14 |
| 04a91508-c4180d4b1af | Company 3 |
| 05070c61-15e06fcb45f | Company 19 |
| 05e1c63e-60d80bec44a | Company 18 |
| 072a211e-e392b853757 | Company 4 |
| 0d8219ed-31077dfc7ea | Company 5 |
| 0ed9210e-8146094d589 | Company 3 |
| 20f56fe9-ed325ee400d | Company 6 |
内容的提问来源于stack exchange,提问作者Alastair
相关产品推荐
相关产品推荐

