SQL中如何通过单查询实现t1单列关联t2多序列号列的聚合统计
SQL查询优化调整方案
核心调整目标:在不改变原有t1.age > 2过滤逻辑、按date/type分组统计t1有效行数的统计口径前提下,扩展t1.serial_number与t2表的匹配范围,支持同时匹配serial_number_x、serial_number_y、serial_number_z任意一列的取值。
方案1:直接扩展JOIN条件(写法最简)
直接在原左关联的ON子句中,把单值匹配扩展为多列任意命中即可,写法上用IN替代冗余的多组OR判断,语法更简洁。
调整后完整SQL如下:
select t1.date, t1.type, count(t1.serial_number) as qty from t1 left join t2 on t1.serial_number in (t2.serial_number_x, t2.serial_number_y, t2.serial_number_z) where true and t1.age > 2 group by t1.date, t1.type
注意该方案的适用前提:t2表中不存在多行同时命中同一个t1.serial_number的情况(比如同一序列号分别出现在t2不同行的x列、y列,或同一行的多个列同时和t1.serial_number相等),否则左关联后会放大t1的原始行数,导致最终统计的qty数值偏大。
方案2:预聚合去重后关联(统计口径最稳妥)
如果t2表存在多列重复、多行重复的序列号情况,建议先把t2的三个序列号列提取为统一的去重序列号列表,再和t1做左关联,从根源上避免t1行数被关联逻辑放大,完全和原统计口径保持一致。
调整后完整SQL如下:
select t1.date, t1.type, count(t1.serial_number) as qty from t1 left join ( -- 分别提取三个列的序列号并提前去重,再合并为统一的序列号集合 select distinct serial_number_x as sn from t2 union all select distinct serial_number_y as sn from t2 union all select distinct serial_number_z as sn from t2 ) t2_serial_map on t1.serial_number = t2_serial_map.sn where true and t1.age > 2 group by t1.date, t1.type
方案优势:
- 每个序列号在映射表中只保留一条记录,无论
t2本身的列值有多少重复,都不会在关联时重复匹配t1的行 - 子查询内提前对每个列做
distinct去重,再用union all合并,避免union自带的全局排序去重开销,大表场景下性能更优
常见避坑提示
- 全程保留
left join逻辑,不要为了匹配多列把关联改成inner join,否则会过滤掉t1中没有匹配上t2序列号的行,和原查询的统计范围不一致 - 不要把
t2的匹配条件写到where子句中,否则会把左关联隐式转为内关联,丢失未匹配的t1数据 - 如果后续统计完全不需要用到
t2表的字段,仅需要判断匹配关系,可进一步用exists替代关联逻辑,减少数据匹配的计算量
内容的提问来源于stack exchange,提问作者nomnom3214
相关产品推荐
相关产品推荐

