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

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

      
       有体育赛事信息实体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效率更高,除了和使用索引有关外,更深入的我也在学习中。也希望能得到各位前辈的指点!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于将left join没有匹配的结果替换成0的需求,可以使用coalesce函数来实现。coalesce函数用于返回参数列表的第一个非null值,因此可以将left join的结果字段与0进行比较,如果为null,则替换为0。 例如,假设我们有两个表A和B,通过left join连接它们,并想要将B表没有匹配的结果替换成0,可以使用以下SQL语句: ``` SELECT A.column1, coalesce(B.column2, 0) AS column2 FROM A LEFT JOIN B ON A.id = B.id ``` 在这个例子,如果B表没有与A表匹配的记录,coalesce函数将返回0,替换B表的column2字段。 引用提到的left join原理是首先确保左表数据全部返回,然后应用on后指定的条件。因此,在left join的结果,如果右表没有与左表匹配的记录,相关字段将被设置为null。通过使用coalesce函数,我们可以将这些null值替换为0,以满足你的需求。这样就实现了将left join没有的结果替换成0的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [SQL优化--inner、left join替换in、not in、except](https://blog.csdn.net/tanghuan0827/article/details/110441136)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值