sql existst in

  • SQL子查询可以分为相关子查询和非相关子查询两类。
    相关子查询的执行依赖于外部查询。多数情况下是子查询的WHERE子句中引用了外部查询的表。
    执行过程:
    (1)从外层查询中取出一个元组,将元组相关列的值传给内层查询。
    (2)执行内层查询,得到子查询操作的值。
    (3)外查询根据子查询返回的结果或结果集得到满足条件的行。
    (4)然后外层查询取出下一个元组重复做步骤1-3,直到外层的元组全部处理完毕。
  • exists对主表用loop逐条查询,每次查询都会查看exists的条件语句,当 exists里的条件语句能够返回记录行时(无论记录行是的多少,只要能返回),条件就为真,返回当前loop到的这条记录,反之如果exists里的条 件语句不能返回记录行,则当前loop到的这条记录被丢弃
    select A from table where exists。。。
    并没有把A的每一个可能的取值去做group by,把与它相关的元素作为一个集合,去看是否exist。
    所以exists内通常会有一个连接查询,起到这个groupby的作用。
  • 对于下表
工程信息
insert into SPJ(Sno,Pno,Jno,QTY)
values
('S1','P1','J1',200),
('S1','P1','J3',100),
('S1','P1','J4',700),
('S1','P2','J2',100),
('S2','P3','J1',400),
('S2','P3','J2',200),
('S2','P3','J4',500),
('S2','P3','J5',400),
('S2','P5','J1',400),
('S2','P5','J2',100),
('S3','P1','J1',200),
('S3','P3','J1',200),
('S4','P5','J1',100),
('S4','P6','J3',300),
('S4','P6','J4',200),
('S5','P2','J4',100),
('S5','P3','J1',200),
('S5','P6','J2',200),
('S5','P6','J4',500);

若想返回存在 qty=100 and sno='S1’的列的jno,错误的方式是

select Jno from spj where exists (select * from spj where qty=100 and sno='S1')
结果是返回了19个Jno,对于每个Jno exists子句执行的都是同一个操作,去看spj这个表中有没有qty=100 and sno='S1'的行

正确 ( a.Jno=b.Jno这个连接查询,起到groupby的作用)

select Jno from spj a where exists (select * from spj b where qty=100 and sno='S1' and a.Jno=b.Jno)
select Jno from spj a where qty=100 and sno='S1' 
  • 找出没有使用来自天津的零件厂商的工程
零件厂商
insert into S(Sno,Sname,Status,City)
values
('S1','精益','20','天津'),
('S2','盛锡','10','北京'),
('S3','东方红','30','北京'),
('S4','丰泰盛','20','天津'),
('S5','为民','30','上海');

select sno,pno,jno,qty from spj where pno in(select pno from p  where weight>(select avg(weight) from p))
insert into P(Pno,Pname,color,weight)
values
('P1','螺母','红',12),
('P2','螺栓','绿',17),
('P3','螺丝刀','蓝',14),
('P4','螺丝刀','红',14),
('P5','凸轮','蓝',40),
('P6','齿轮','红',30);

工程信息
insert into J(Jno,Jname,CITY)
values
('J1','三建','北京'),
('J2','一汽','长春'),
('J3','弹簧厂','天津'),
('J4','造船厂','天津'),
('J5','机车厂','唐山'),
('J6','无线电厂','常州'),
('J7','半导体厂','南京');



insert into SPJ(Sno,Pno,Jno,QTY)
values
('S1','P1','J1',200),
('S1','P1','J3',100),
('S1','P1','J4',700),
('S1','P2','J2',100),
('S2','P3','J1',400),
('S2','P3','J2',200),
('S2','P3','J4',500),
('S2','P3','J5',400),
('S2','P5','J1',400),
('S2','P5','J2',100),
('S3','P1','J1',200),
('S3','P3','J1',200),
('S4','P5','J1',100),
('S4','P6','J3',300),
('S4','P6','J4',200),
('S5','P2','J4',100),
('S5','P3','J1',200),
('S5','P6','J2',200),
('S5','P6','J4',500);
  • 用not in 的正确表达
select  distinct Jno from SPJ where Jno 
not in (select Jno from SPJ,S   
where  SPJ.Sno=S.Sno  and  S.City='天津' )
  • 用not in 的错误表达
select  distinct Jno from SPJ,S where  SPJ.Sno=S.Sno  and
 Jno not in (select Jno from SPJ  where  S.City='天津' )

实际执行中,对于每一个 SPJ.Sno=S.Sno,执行了where的第二个条件。而不是执行完SPJ.Sno=S.Sno后把连接好的整张表送给第二个条件去执行。

  • 用 not exists的正确表达
select a.Jno from Spj a where not exists 
( select * from SPJ b,S where a.Jno=b.Jno and S.Sno=SPJ.Sno and City='天津') 
select a.Jno from Spj a where not exists 
( select * from SPJ b where a.Jno=b.Jno and b.Jno 
in(select SPJ.Jno from SPJ,S where S.Sno=SPJ.Sno and City='天津') )

select  a.Jno from SPJ a where not exists (select * from 
(select City,SPJ.Jno from SPJ,S where SPJ.Sno=S.Sno) as b 
where a.Jno=b.Jno and b.City='天津' )
  • 错误
select distinct a.Jno from SPJ a,S,J where a.Sno=S.Sno and not exists (select * from SPJ b where a.Jno=b.Jno and S.City='天津' )

相当于把Sno不同的条目都拆开了之后再送给exists判断

select Jno from Spj where not exists (select * from SPJ,S where SPJ.Sno in(select SPJ.Sno from SPJ,J where S.Sno=SPJ.Sno and City='天津') )

对于每个Jno exists子句执行的都是同一个操作,去看spj这个表中有没有city是天津的

  • 查询至少使用了供应商S1所供应的全部零件的城是(CITY)(不一定要由s1供应)
select city  from j where not exists (select * from spj a where a.sno='S1' and not exists(select * from spj b where a.pno=b.pno and b.jno=j.jno))

select a From Ta where not exists(select * from Tx1 where b…and select * from Tx2 where Tx2.a=Ta.a and Tx2.b=Tx1.b)
对于所有的符合某条件的b,a都。。。
等价于不存在这样的的b,b符合某条件,但a没有与它相关的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值