MySQL无需子查询和GROUP BY实现关联表时获取另一表字段最小值的方法
解决方案
可以使用自关联左连接+空值判断的方式实现,无需显式写子查询和GROUP BY,写法如下:
SELECT A.*, C.id AS complete_date FROM A INNER JOIN C ON A.id = C.A_id LEFT JOIN C AS C_smaller ON C.A_id = C_smaller.A_id AND C_smaller.id < C.id WHERE A.status = 'complete' AND C_smaller.id IS NULL;
实现逻辑
- 先关联A表和C表拿到所有匹配的关联行
- 再左联C表的别名
C_smaller,匹配规则为同属于一个A_id,且C_smaller.id小于当前关联的C表行的id - 最后加
C_smaller.id IS NULL的过滤条件:如果没有匹配到更小的id,说明当前C表的id就是该A_id对应的最小值
性能说明
- 如果C表已经建立了
(A_id, id)的联合索引,该方案的性能和原有子查询+GROUP BY的方案基本持平,部分数据库优化器对这种关联查询的优化效率甚至会高于分组聚合 - 如果C表单个A_id下的关联行数非常多,原有GROUP BY方案的效率会更高,建议结合实际业务数据量做压测选择最优方案
- 如果需要保留A表中没有对应C表关联的行(对应原始需求的LEFT JOIN效果),把
INNER JOIN C改成LEFT JOIN C即可 - 若C表存在同一个A_id下多条id相同的行,需要在SELECT后加
DISTINCT去重,若C.id是主键则无需处理
内容的提问来源于stack exchange,提问作者Karthikeyan KR
相关产品推荐
相关产品推荐

