sql的not exists随笔

本文探讨了SQL中EXISTS与IN、NOT EXISTS与NOT IN的区别及效率对比,并通过实例展示了如何根据实际情况选择合适的语法以优化查询性能。

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

简单的理解就是 not exists = not in;exists= in

 

但这只是简单的理解而已,其里面的执行机制和细微处还是有一定的差别!

 

以下是从网络上摘录下的文章:

 

SQL里的EXISTS与in、 not exists与 not in 效率比较和使用

在 MSSQL 中,插入(insert)一条记录很简单,但是一些特殊应用,在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,本文介绍的就是这个问题的解决方案。


问题: 我创建了一个表来存放客户信息,我知道可以用 insert 语句插入信息到表中,但是怎么样才能保证不会插入重复的记录呢?

答案: 可以通过使用 EXISTS 条件句防止插入重复记录。


示例一:插入多条记录

假设有一个主键为 client_id 的 clients 表,可以使用下面的语句:

Code:


INSERT INTO clients
(client_id, client_name, client_type)
SELECT supplier_id, supplier_name, 'advertising'
FROM suppliers
WHERE not exists (select * from clients
where clients.client_id = suppliers.supplier_id);

 

个人批注:not exists不存在,也就是说后面的括号中只要返回了数据那么这个条件就不存在了,可以理解为括号前的not

exists是一个左表达式 ,括号后的查询是一个右表达式,只有当右表达式返回的也是not exists(即后面的查询出来的结果是非空的)时,等式才成立。

 



示例一:插入单条记录

Code:


INSERT INTO clients
(client_id, client_name, client_type)
SELECT 10345, 'IBM', 'advertising'
FROM dual
WHERE not exists (select * from clients
where clients.client_id = 10345);



使用 dual 做表名可以让你在 select 语句后面直接跟上要插入字段的值,即使这些值还不存在当前表中。

系统要求进行SQL优化,对效率比较低的SQL进行优化,使其运行效率更高,其中要求对SQL中的部分in/not in修改为exists/not exists

修改方法如下:

in的SQL语句

SELECT id, category_id, htmlfile, title, convert(varchar(20),begintime,112) as pubtime
FROM tab_oa_pub WHERE is_check=1 and
category_id in (select id from tab_oa_pub_cate where no='1')
order by begintime desc

修改为exists的SQL语句
SELECT id, category_id, htmlfile, title, convert(varchar(20),begintime,112) as pubtime
FROM tab_oa_pub WHERE is_check=1 and
exists (select id from tab_oa_pub_cate where tab_oa_pub.category_id=convert(int,no) and no='1')
order by begintime desc

分析一下exists真的就比in的效率高吗?

    我们先讨论IN和EXISTS。
    select * from t1 where x in ( select y from t2 )
    事实上可以理解为:
    select *
      from t1, ( select distinct y from t2 ) t2
     where t1.x = t2.y;
    ——如果你有一定的SQL优化经验,从这句很自然的可以想到t2绝对不能是个大表,因为需要对t2进行全表的“唯一排序”,如果t2很大这个排序的性能是不可忍受的。但是t1可以很大,为什么呢?最通俗的理解就是因为t1.x=t2.y可以走索引。但这并不是一个很好的解释。试想,如果t1.x和t2.y都有索引,我们知道索引是种有序的结构,因此t1和t2之间最佳的方案是走merge join。另外,如果t2.y上有索引,对t2的排序性能也有很大提高。
    select * from t1 where exists ( select null from t2 where y = x )
    可以理解为:
    for x in ( select * from t1 )
    loop
       if ( exists ( select null from t2 where y = x.x )
       then
          OUTPUT THE RECORD!
       end if
    end loop
    ——这个更容易理解,t1永远是个表扫描!因此t1绝对不能是个大表,而t2可以很大,因为y=x.x可以走t2.y的索引。
    综合以上对IN/EXISTS的讨论,我们可以得出一个基本通用的结论:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

我们要根据实际的情况做相应的优化,不能绝对的说谁的效率高谁的效率低,所有的事都是相对的

 

### SQL 中 `NOT EXISTS` 的用法 `NOT EXISTS` 是一种用于子查询的关键字,通常用来测试是否存在满足特定条件的结果集。如果子查询返回空结果,则整个表达式的布尔值为真;否则为假。 #### 使用场景 当需要查找某些记录不存在于另一张表中的情况时,可以使用 `NOT EXISTS` 来实现这一逻辑[^1]。它常被应用于复杂的多表关联查询中,尤其是涉及否定条件的情况下。 以下是具体的语法和示例: --- #### 语法结构 ```sql SELECT column_list FROM table_name AS outer_query WHERE NOT EXISTS ( SELECT * FROM another_table AS inner_query WHERE condition_between_outer_and_inner_queries); ``` - **outer_query**: 外层查询所操作的主要表格。 - **inner_query**: 子查询部分,在这里定义与外层查询的关系以及过滤条件。 - **condition_between_outer_and_inner_queries**: 连接内外两层查询的条件语句。 --- #### 示例代码 假设我们有两个表:`employees` 和 `departments`。现在希望找到那些没有任何部门分配给他们的员工名单。 ```sql -- 主表 employees 包含所有雇员的信息 -- 辅助表 departments 记录各部门及其对应的负责人信息 SELECT e.name, e.id FROM employees AS e WHERE NOT EXISTS ( SELECT d.employee_id FROM departments AS d WHERE d.employee_id = e.id); -- 判断是否有对应关系存在 ``` 上述例子通过嵌套的方式实现了只选取未加入任何部门管理下的个人资料列表的功能[^2]。 另外需要注意的是,虽然也可以采用左连接加 NULL 检查的方法来完成相同任务 (`LEFT JOIN ... IS NULL`) ,但在性能表现上可能因具体数据库引擎而异,因此推荐根据实际情况选用最合适的方案[^3]。 --- #### 性能考量 对于大规模数据集合而言,合理设计索引能够显著提升带有 `EXISTS/NOT EXISTS` 查询的速度。特别是针对内部子查询涉及到频繁访问字段建立适当索引尤为重要[^4]。 --- ### 结论 综上所述,掌握了如何正确运用 `NOT EXISTS` 后可以帮助开发者更高效地处理复杂业务需求下关于排除型筛选的问题解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值