Mysql exists和in

今天在学习sql语句时,遇到关于exsits的用法,下面是题目:

表架构

Student(S#,Sname,Sage,Ssex) 学生表 
Course(C#,Cname,T#) 课程表 
SC(S#,C#,score) 成绩表 
Teacher(T#,Tname) 教师表

问题:

查询学过“001”并且也学过编号“002”课程的同学的学号、姓名:

  即执行主句查询前,先查询是否子句是否为真,若存在学过002课程的学生,再执行查询学过001的,

此时查询出来的结果,就符合既学过001又学过002。

select Student.`S#`,Student.Sname from Student,SC where Student.`S#`=SC.`S#` and SC.`C#`='001'and exists(
Select * from SC as SC_2 where SC_2.`S#`=SC.`S#` and SC_2.`C#`='002');

由此对比in和exsits的用法:

exsits:

exsits子句返回的并非查询结果,而是布尔值,TRUE或者FALSE,exists对外表用loop逐条查询,

每次查询都会查看exists的条件语句,当 exists里的条件语句,能够返回记录行时(无论记录行是的多少,只要能返回),条件就为真

返回当前loop到的这条记录,反之如果exists里的条件语句不能返回记录行,则当前loop到的这条记录被丢弃,exists的条件就像一个bool条件,

当能返回结果集则为true,不能返回结果集则为 false。

In:

 in查询相当于多个or条件的叠加,这个比较好理解,比如下面的查询:

select * from user where userId in (1, 2, 3);

等效于

select * from user where userId = 1 or userId = 2 or userId = 3;

not in与in相反,如下

select * from user where userId not in (1, 2, 3);

等效于

select * from user where userId != 1 and userId != 2 and userId != 3;

总的来说,in查询就是先将子查询条件的记录全都查出来,假设结果集为B,共有m条记录,然后在将子查询条件的结果集分解成m个,再进行m次查询

值得一提的是,in查询的子条件返回结果必须只有一个字段,例如

select * from user where userId in (select id from B);

而不能是

select * from user where userId in (select id, age from B);

而exists就没有这个限制

性能方面对比:

1: select * from A where exists (select * from B where B.id = A.id);

2: select * from A where A.id in (select id from B);

查询1.可以转化以下伪代码,便于理解

for ($i = 0; $i < count(A); $i++) {

  $a = get_record(A, $i); #从A表逐条获取记录

  if (B.id = $a[id]) #如果子条件成立

    $result[] = $a;

}

return $result;

大概就是这么个意思,其实可以看到,查询1主要是用到了B表的索引,A表如何对查询的效率影响应该不大

假设B表的所有id为1,2,3,查询2可以转换为

select * from A where A.id = 1 or A.id = 2 or A.id = 3;

这个好理解了,这里主要是用到了A的索引,B表如何对查询影响不大。

原文地址:https://www.cnblogs.com/kunpengv5/p/7859796.html