SQL 中 IN 和 NOT IN 用法的那些事

好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受.

老是说面试,没啥意思,今天说点技术的东西,

一、SQL中的IN 和 NOT IN 

(一)基本概念

  • IN :用于指定一个标量值的列表,用于匹配查询结果中是否包含列表中的值。例如:SELECT column_name(s) FROM table_name WHERE column_name IN (value1, value2, ...)

  • NOT IN :用于指定一个标量值的列表,用于匹配查询结果中是否不包含列表中的值。例如:SELECT column_name(s) FROM table_name WHERE column_name NOT IN (value1, value2, ...)

(二)潜在问题

  • 效率低 :在某些情况下,尤其是数据量较大时,IN 和 NOT IN 的查询效率可能较低。例如,当子查询返回大量数据时,使用 IN 的查询可能需要进行全表扫描,导致查询速度变慢。

  • 容易出错 :在使用 IN 时,如果不小心在子查询中写错了列名,可能会导致查询结果不准确,而且不会报错。对于 NOT IN,如果子查询中包含 NULL 值,那么整个查询结果可能会为空,这可能与预期不符。

二、它们在不同数据库中的使用限制和区别

(一)MySQL

  • 使用限制 :在 MySQL 中,IN 和 NOT IN 的使用基本遵循标准 SQL 的规则。对于子查询返回的结果集,需要注意其返回的值类型应与主查询中的列类型一致。如果子查询返回的结果集中包含 NULL 值,那么使用 NOT IN 时可能会导致查询结果为空。

  • 性能优化 :在某些情况下,MySQL 对 IN 和 NOT IN 的查询可能会进行自动优化。但为了提高查询效率,建议尽量避免在子查询中使用复杂的查询逻辑,或者在子查询中包含大量数据。可以考虑使用 EXISTS 或 JOIN 代替。

(二)Oracle

  • 使用限制 :Oracle 对 IN 和 NOT IN 的使用也有类似的标准 SQL 规则。同样需要注意子查询返回的结果集类型与主查询列类型的一致性。对于 NOT IN,若子查询结果中存在 NULL 值,查询结果可能不会符合预期。

  • 性能优化 :Oracle 通常会根据查询语句的执行计划和表的统计信息来优化查询。在使用 IN 和 NOT IN 时,如果子查询的结果集较大,可能会导致查询效率降低。可以通过调整查询语句的写法,如使用 EXISTS 或 JOIN,来提高查询性能。
    记住:oracle 有in 1000 的限制哦

(三)SQL Server

  • 使用限制 :在 SQL Server 中,IN 和 NOT IN 的使用遵循标准 SQL 规范。需要注意子查询返回值与主查询列的类型匹配问题。对于 NOT IN,当子查询包含 NULL 值时,查询结果可能出现异常。

  • 性能优化 :SQL Server 会根据查询语句的执行计划和索引等来优化查询性能。在某些情况下,使用 IN 和 NOT IN 可能会导致查询效率低下。可以尝试使用 EXISTS 或 JOIN 等其他查询方式来代替,以提高查询效率。

(四)DB2

  • 使用限制 :DB2 对 IN 和 NOT IN 的使用规则与标准 SQL 相符。在使用过程中,要注意子查询返回结果的类型与主查询列的类型一致。当使用 NOT IN 且子查询结果中存在 NULL 值时,查询结果可能不符合预期。

  • 性能优化 :DB2 会根据查询语句的执行计划和表的结构等来优化查询。如果使用 IN 和 NOT IN 的查询性能不理想,可以考虑使用其他查询方式,如 EXISTS 或 JOIN,来提高查询效率。

  • 相知不迷路,来者皆是兄弟,搜索公众号 :“codingba” or “码出精彩” 交朋友,有更多资源相送。

三、替代方案

(一)使用 EXISTS 或 NOT EXISTS 代替

  • 语法示例

    • 使用 EXISTS:SELECT * FROM test1 WHERE EXISTS (SELECT * FROM test2 WHERE id2 = id1)

    • 使用 NOT EXISTS:SELECT * FROM test1 WHERE NOT EXISTS (SELECT * FROM test2 WHERE id2 = id1)

  • 优点 :EXISTS 和 NOT EXISTS 的查询效率通常比 IN 和 NOT IN 更高,特别是在子查询返回的结果集较大时。而且不存在因子查询包含 NULL 值而导致 NOT IN 查询结果为空的问题。

(二)使用 JOIN 代替

  • 语法示例

    • 使用 INNER JOIN:SELECT id1 FROM test1 INNER JOIN test2 ON id2 = id1

    • 使用 LEFT JOIN:SELECT id1 FROM test1 LEFT JOIN test2 ON id2 = id1 WHERE id2 IS NULL

  • 优点 :通过 JOIN 查询可以将多个表的数据进行关联查询,查询效率通常较高,而且可以避免因子查询出错而导致的结果不准确问题。

综上所述,在使用 SQL 中的 IN 和 NOT IN 时,需要注意其潜在的问题,如效率低和容易出错等。在不同数据库(MySQL、Oracle、SQL Server、DB2)中,它们的使用规则基本一致,但在性能优化方面可能存在差异。为了提高查询效率和准确性,可以考虑使用 EXISTS、NOT EXISTS 或 JOIN 等方式代替 IN 和 NOT IN。在实际应用中,应根据具体的需求和数据库的特点来选择合适的查询方式。

### SQL中`IN``NOT IN`操作符的使用方法及区别 `IN``NOT IN`是SQL语言中用于子句匹配的关键字,通常在`WHERE`条件中使用。它们的主要功能是对某个字段的值是否存在于一个指定的集合中进行判断。 #### `IN` 操作符 `IN`用于检查某个字段的值是否包含在指定的集合中。如果字段的值存在于集合中,则条件为真,并返回对应的记录。语法如下: ```sql SELECT column_name(s) FROM table_name WHERE column_name IN (value1, value2, ..., valueN); ``` 例如,查询表A中ID为1、3或5的记录: ```sql SELECT ID, NAME FROM A WHERE ID IN (1, 3, 5); ``` `IN`也可以与子查询结合使用,用来动态生成需要匹配的集合。例如,查找表A中所有ID存在于表B中的记录: ```sql SELECT ID, NAME FROM A WHERE ID IN (SELECT AID FROM B); ``` `IN`操作符等价于多个`OR`条件的组合。虽然其语法较为简洁,但在某些情况下可能会导致性能问题,尤其是当子查询无法利用索引时,效率可能不如`EXISTS` [^1]。 #### `NOT IN` 操作符 `NOT IN`的功能与`IN`相反,它用于筛选出那些字段值不在指定集合中的记录。如果字段的值不存在于集合中,则条件为真,并返回对应的记录。语法如下: ```sql SELECT column_name(s) FROM table_name WHERE column_name NOT IN (value1, value2, ..., valueN); ``` 例如,查询表A中ID不等于1、3且不等于5的记录: ```sql SELECT ID, NAME FROM A WHERE ID NOT IN (1, 3, 5); ``` 同样,`NOT IN`也可以与子查询一起使用。例如,查找表A中所有ID不在表B中的记录: ```sql SELECT ID, NAME FROM A WHERE ID NOT IN (SELECT AID FROM B); ``` 需要注意的是,当子查询结果集中包含`NULL`值时,`NOT IN`的行为会变得不可预测。例如,在引用[^3]中提到的示例中,如果表tb1中存在`NULL`值,则可能导致查询结果不符合预期。因此,在使用`NOT IN`时,应特别注意子查询结果集中的`NULL`情况。 #### `IN` `NOT IN` 的区别 - **逻辑含义**:`IN`表示字段值必须存在于指定集合中,而`NOT IN`表示字段值必须不存在于指定集合中。 - **性能表现**:在处理大量数据时,`IN`可能比`EXISTS`效率低,因为`IN`子查询有时不能有效利用索引。相比之下,`EXISTS`通常通过半连接优化来提高查询性能 [^1]。 - **对`NULL`值的处理**:`IN`对于明确的值列表能够正常工作,但如果子查询返回的结果集中包含`NULL`值,`NOT IN`可能会导致意外结果。例如,当子查询返回`(NULL, 1)`时,`NOT IN (NULL, 1)`将始终返回未知状态,从而不会选择任何记录 [^3]。 #### 示例代码 以下是一些常见的使用场景示例: 1. 使用`IN`查询特定集合中的记录: ```sql SELECT * FROM Employees WHERE DepartmentID IN (101, 102, 103); ``` 2. 使用`NOT IN`排除特定集合中的记录: ```sql SELECT * FROM Customers WHERE Country NOT IN ('USA', 'Canada'); ``` 3. 结合子查询使用`IN`: ```sql SELECT * FROM Orders WHERE CustomerID IN (SELECT ID FROM Customers WHERE Country = 'Germany'); ``` 4. 结合子查询使用`NOT IN`(需注意`NULL`值): ```sql SELECT * FROM Products WHERE CategoryID NOT IN (SELECT CategoryID FROM DiscontinuedCategories); ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值