一、用法
exists: ()內子查詢語句返回結果不為空,說明where條件成立就會執行主sql語句。如果為空就表示where條件不成立,sql語句就不會執行。not exists 和 exists相反,子查詢語句結果為空,則表示where條件成立,執行sql語句。否則不執行。
exists : 強調是否返回結果集,不要求知道返回什么,與in的區別就是,in只能返回一個字段值,exists允許返回多個字段。如:
select name from student where sex = 'm' and mark exists(select 1 from grade where ...)
exists引導的子句有結果集返回,那么exists這個條件就算成立了,返回的字段始終為1,這個數字沒有意義。所以exists子句不在乎返回什么,而是在乎是不是有結果集返回。
- exists (sql返回的結果為真)
- not exists (sql不返回的結果為真)
exists 效率一般優于 in ,使用EXISTS,Oracle會首先檢查主查詢,然后運行子查詢知道它找到第一個匹配項,這就節省了時間。IN 子查詢時,首先執行子查詢,并將獲得的結果列表存放在一個加了索引的臨時表中。
exists 效率優于DISTINCT 當,提交一對多表信息的查詢時,避免在SELECT 子句中使用DISTINCT
exists適合外表的結果集小的情況
in適合內外表都很大的情況
二、實例
1.exists簡單用法
create table a(
id int,
name varchar(10)
);
insert into a values(1,'A1');
insert into a values(2,'A2');
insert into a values(3,'A3');
1.png
create table b(
id int,
aid int,
name varchar(10)
);
insert into b values(1,1,'B1');
insert into b values(2,2,'B2');
insert into b values(3,2,'B3');
2.png
表A和表B示1對多的關系 A.ID => B.AID
SELECT ID,NAME FROM A WHERE
EXISTS(SELECT * FROM B WHERE A.ID = B.AID)
執行結果:
3.png
分解
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=1)
--->SELECT * FROM B WHERE B.AID=1有值返回TRUE所以有數據
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=2)
--->SELECT * FROM B WHERE B.AID=2有值返回TRUE所以有數據
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=3)
--->SELECT * FROM B WHERE B.AID=3無值返回TRUE所以沒有數據
- NOT EXISTS 就是反過來
以上代碼等價于:
SELECT id, name from A WHERE id in (
select aid from B)
SQL中IN, NOT IN, EXISTS, NOT EXISTS 的用法和差別:
- IN:確定給定的值是否與子查詢或列表中的值相匹配。IN關鍵字選擇與列表中的任意一個值匹配的行。IN 關鍵字之后的項目必須用逗號隔開,并且括在括號中。
- NOT IN : 通過 NOT IN 關鍵字引入的子查詢也返回一列零值或更多值。
- EXISTS 指定一個子查詢,檢測行的存在。相當于兩個集合的交集。EXISTS 后面可是整句的查詢語句,IN的后面只能是對單列。
- NOT EXISTS 相當于兩個集合的差集。
- EXISTS 和 NOT EXISTS 返回的結果類型是 Boolean,如果子查詢包含行,則返回TRUE/FALSE
二、EXISTS 替代DISTINCT
SELECT distinct dept_no, dept_name from dept D, EMP E
WHERE D.dept_no = E.dept_no;
SELECT dept_no, dept_name from dept D
WHERE EXISTS (
SELECT 1 from emp E WHERE E.dept_no =D.dept_no
);
RDBMS 核心模塊將在子查詢的條件一旦滿足后,立即返回結果,所以自帶去重。
三、按A列去重,按B列取條件(如最大/小值等)
-
在下表中查詢出,同一ID內的B_DATE最近的記錄。
4.png
SELECT * from t t1
WHERE NOT EXISTS(
select * from t where id = t1.id and b_date>t1.b_date)
結果:
5.png
分析:
子查詢中,先看id = 1 的情形,只有當t1.b_date 取最大值時,沒有返回結果,因為是NOT EXISTS關鍵字,所以Where條件成立,返回符合條件的查詢結果。