SQL查询性能优化 之 LEFT JOIN 替换 NOT IN

本文探讨了在数据库查询中如何使用LEFT JOIN替代NOT IN来提高查询效率,并给出了具体的SQL语句实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       今天工作的时候遇到一个需求,如下:

      
       有体育赛事信息实体Game,Game可以在后台管理系统中被指定为APP或者PC网站的首页推荐,当一个赛事(Game)被指定为首页推荐后,在客户端看到的效果是,被推荐赛事的一张大图加入到首页轮播(HomeSlideShow)中,点击图片,即可跳转到相对应的赛事详情页。


       客户要求每个赛事赛事(Game)只能被推荐一次,不能重复推荐。


       现有赛事信息表game, 和首页推荐表slideshow,字段如下


Game 
IDvarchar(50)
NAMEvarchar(50)

SlideShow 
IDvarchar(50)
GIDvarchar(50)
TITLEvarchar(100)



       在组织SQL语句,查询未添加过首页推荐的赛事(Game)时,很容易写成:

      

   SELECT ID, NAME FROM Game WHERE ID NOT IN (SELECT GID FROM SlideShow);

       我们知道NOT IN的查询效率是非常低的,因为它不能使用索引,大大降低查询效率。


       那么,在需要NOT IN的时候如何用什么替代它能?


       常见的可以使用LEFT JOIN...IS NULL的方式达到同样的目的。


       例如上面的SQL可以改成:


   SELECT ID, NAME FROM (SELECT g.ID, g.NAME s.GID FROM Game g LEFT JOIN SlideShow s ON(g.ID = s.GID)) c WHERE c.GID IS NULL;

       这里主要用到了左向外联接的结果集包括  LEFT (OUTER)子句中指定的左表(这里指Game)的所有行,而不仅仅是联接列(Game.ID和SlideShow.GID)所匹配的行。如果左表(Game)的某行在右表(SlideShow)中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。


       也就是说,我们把Game表和SlideShow两张表拿出来按照Game.ID = SlideShow.GID的规则对比一下,生成一个临时表c(也可以理解成把两张表按照上述规则合并一下,合并后的表是c,这里并没有真正生成物理上的表c)。理论上SlideShow中GID都可以在Game表的ID列找到对应的值,反之在SlideShow的GID的列并不一定能找到Game表中ID列上的所有值,所以,我们通过左联接查询,发现c.GID的为空,那么就意味着该行的c.ID就是我们需要的Game的ID。


       虽然这篇文章的标题是用LEFT JOIN 代替 NOT IN,但在上面的解释中,我并没有说一定要用左外连接代替NOT IN,而不能用RIGHT JOIN。因为RIGHT JOIN也是可以的,道理都是一样的。例如你也可以把上面的左外联接改成下面的右外连接查询:


   SELECT ID, NAME FROM (SELECT g.ID, g.NAME s.GID FROM SlideShow s RIGHT JOIN Game g ON(g.ID = s.GID)) c WHERE c.GID IS NULL;


       具体NOT IN如何影响SQL性能、以及上述方法为什么比用NOT IN效率更高,除了和使用索引有关外,更深入的我也在学习中。也希望能得到各位前辈的指点!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值