如何基于一对多关联关系通过JOIN查询筛选用户并避免重复结果
重复结果的成因
直接将用户表和全量订单表做INNER JOIN时,同一个用户如果匹配到多条符合筛选条件的订单记录,系统会将每一条匹配的订单都对应生成一行查询结果。比如示例中user_id=1的Chris,一共匹配到2条prod1订单、1条prod2订单,最终查询会返回3条重复的用户记录,和预期的“每个符合条件的用户仅返回一行”的要求不符。
基于JOIN逻辑的优化实现
可以通过两种不脱离JOIN用法的方式消除重复,匹配预期输出:
- 方式1:关联后对结果做用户字段去重
直接在查询中指定需要返回的用户字段,搭配DISTINCT关键字去掉完全重复的用户行,写法简洁直接:
注意:这里不能沿用原查询的SELECT DISTINCT user.user_id, user.name FROM user INNER JOIN orders ON user.user_id = orders.user_id WHERE orders.product IN ('prod1', 'prod2');SELECT *写法,否则会因为返回的订单product字段值不同,无法触发去重效果,必须只选取用户表需要输出的字段做去重。如果实际筛选目标仅为订购过prod1的用户,只需要将过滤条件替换为orders.product = 'prod1'即可,其余逻辑不变 - 方式2:先聚合订单侧的有效用户,再和用户表关联
这种写法在订单表数据量大时性能表现更好,因为提前将参与关联的订单侧数据量压缩到最小,避免全表关联带来的冗余计算:SELECT user.user_id, user.name FROM user INNER JOIN ( -- 提前筛选出所有购买过目标商品的去重用户ID SELECT DISTINCT user_id FROM orders WHERE product IN ('prod1', 'prod2') ) valid_user ON user.user_id = valid_user.user_id;
原查询的细节优化
原写法中用OR连接多个等值判断的过滤条件,完全可以替换为可读性更强的IN运算符,简化条件书写,也减少逻辑写错的概率。
内容的提问来源于stack exchange,提问作者user15512354
相关产品推荐
相关产品推荐

