如何避免Left Join查询返回的记录数多于主表原始记录数?
问题原因
记录数变多的根本原因是左连接的特性:右表如果存在多个和关联键匹配的行,每多一个匹配项就会生成一行新的结果。你新增关联table_d的时候用table_b.id作为关联键,只要有一个table_b.id在table_d里存在n条匹配记录,原本的1行结果就会拆成n行,总记录数自然就超过了主表table_a的11000条。
另外你写的新增左连接的SQL存在语法错误:Left Join table_d.id是错误写法,正确的关联表语法应该是LEFT JOIN table_d ON table_b.id = table_d.id。
解决方法
- 方法1:先对
table_d做预聚合,保证每个关联id仅对应1行后再关联
如果你需要取table_d的sales字段,可先按照关联键id对table_d做聚合处理,确保单id唯一,再执行左连接。比如你需要统计每个id的销售总额,可按如下方式改写:
如果你需要取最新的单条sales,也可以用窗口函数先对SELECT table_a.id, table_b.location, table_c.material, d.total_sales FROM table_a LEFT JOIN table_b ON table_a.id = table_b.id LEFT JOIN table_c ON table_a.id = table_c.id LEFT JOIN ( SELECT id, SUM(sales) AS total_sales FROM table_d GROUP BY id ) d ON table_b.id = d.idtable_d做行过滤:SELECT table_a.id, table_b.location, table_c.material, d.sales FROM table_a LEFT JOIN table_b ON table_a.id = table_b.id LEFT JOIN table_c ON table_a.id = table_c.id LEFT JOIN ( SELECT id, sales, ROW_NUMBER() OVER (PARTITION BY id ORDER BY 你的时间排序字段 DESC) AS rn FROM table_d ) d ON table_b.id = d.id AND d.rn = 1 - 方法2:用关联子查询替代左连接,避免生成额外行
如果你仅需要从table_d取单个字段的值,可以直接在SELECT子句中写关联子查询,不会触发左连接的行复制逻辑:SELECT table_a.id, table_b.location, table_c.material, (SELECT sales FROM table_d WHERE table_d.id = table_b.id ORDER BY 你的排序字段 LIMIT 1) AS sales FROM table_a LEFT JOIN table_b ON table_a.id = table_b.id LEFT JOIN table_c ON table_a.id = table_c.id - 方法3:排查
table_d的脏数据
如果你的业务逻辑中table_d的id字段应该是唯一主键,那多余的500条记录大概率是table_d存在重复id的脏数据,先清理重复数据后再关联即可保证总记录数和table_a一致。
内容的提问来源于stack exchange,提问作者Xkid
相关产品推荐
相关产品推荐

