子查询 in 潜在的问题 - 建议最好别用

时间:2022-08-29 19:22:51

转至:http://wiki.lessthandot.com/index.php/Subquery_typo_with_using_in

Subquery typo with using in

From Wiki

 
Jump to: navigation, search

Do you use the following syntax?

  1. SELECT *
  2. FROM TABLE
  3. WHERE COLUMN IN (SELECT COLUMN FROM TABLE)
 

OR this?

  1. SELECT *
  2. FROM TABLE
  3. WHERE COLUMN NOT IN (SELECT COLUMN FROM TABLE)
 

Do NOT use that, it will cause problems sooner or later. Don't believe me? Let's take a look

First create these 2 tables and populate them with some sample data

  1. CREATE TABLE TestTable1 (id1 INT)
  2. CREATE TABLE TestTable2 (id2 INT)
  3. INSERT TestTable1 VALUES(1)
  4. INSERT TestTable1 VALUES(2)
  5. INSERT TestTable1 VALUES(3)
  6. INSERT TestTable2 VALUES(1)
  7. INSERT TestTable2 VALUES(2)
 

Now let's run the IN query

  1. SELECT *
  2. FROM TestTable1
  3. WHERE id1 IN (SELECT id2 FROM TestTable2)
 
id1
1
2

No problems here right?

What if by mistake you wrote id1 instead of id2?

  1. SELECT *
  2. FROM TestTable1
  3. WHERE id1 IN (SELECT id1 FROM TestTable2)
 

id1

1
2
3

Oops all 3 rows are returned, if you just run this SELECT id1 FROM TestTable2 you will get this error Server: Msg 207, Level 16, State 3, Line 1 Invalid column name 'id1'.

So what happens? SQL Server sees column id1 and says "yes I have that it is in the TestTable1 table, I can use that" What can we do? Use EXISTS because you will get an error instead of a wrong resultset

  1. SELECT *
  2. FROM t1
  3. WHERE EXISTS (SELECT * FROM TestTable2 t2 WHERE t2.id2 = t1.id1 )
 

id1

1
2

A JOIN will do the same as EXISTS

  1. SELECT t1.*
  2. FROM TestTable1 t1
  3. JOIN TestTable2 t2 ON t2.id2 = t1.id1
 

id1

1
2

Now let's try NOT IN

  1. SELECT *
  2. FROM TestTable1
  3. WHERE id1 NOT IN (SELECT id2 FROM TestTable2)
 

id1

3

No problem right?

Add a NULL value to the TestTable2 table

  1. INSERT TestTable2 VALUES(NULL)
 

Let's try running it again

  1. SELECT *
  2. FROM TestTable1
  3. WHERE id1 NOT IN (SELECT id2 FROM TestTable2)
 

Where are my rows? Nowhere, since NULL is not equal to anything including another NULL SQL just returns nothing

What happens when you use NOT EXISTS?

  1. SELECT *
  2. FROM TestTable1 t1
  3. WHERE NOT EXISTS (SELECT * FROM TestTable2 t2 WHERE t2.id2 = t1.id1 )
 

id1

3

That works without a problem

What about a LEFT JOIN?

  1. SELECT t1.*
  2. FROM TestTable1 t1
  3. LEFT JOIN TestTable2 t2 ON t2.id2 = t1.id1
  4. WHERE t2.id2 IS NULL
 

id1

3

That works without a problem also

So from now on use EXISTS, NOT EXISTS, JOIN and LEFT JOIN

DO NOT use IN or NOT IN ever again!

子查询 in 潜在的问题 - 建议最好别用的更多相关文章

  1. 在SQL Server中为什么不建议使用Not In子查询

        在SQL Server中,子查询可以分为相关子查询和无关子查询,对于无关子查询来说,Not In子句比较常见,但Not In潜在会带来下面两种问题: 结果不准确 查询性能低下       下面 ...

  2. (网页)在SQL Server中为什么不建议使用Not In子查询(转)

    转自博客园宋沄剑  英文名:CareySon : 在SQL Server中,子查询可以分为相关子查询和无关子查询,对于无关子查询来说,Not In子句比较常见,但Not In潜在会带来下面两种问题: ...

  3. SQL Server中INNER JOIN与子查询IN的性能测试

    这个月碰到几个人问我关于"SQL SERVER中INNER JOIN 与 IN两种写法的性能孰优孰劣?"这个问题.其实这个概括起来就是SQL Server中INNER JOIN与子 ...

  4. 【Java EE 学习 28 上】【oracle学习第二天】【子查询】【集合运算】【几种数据库对象】

    一.子查询 1.为什么要使用子查询:问题不能一步求解或者一个查询不能通过一步查询得到. 2.分类:单行子查询和多行子查询. 3.子查询的本质:一个查询中包含了另外一个或者多个查询. 4.使用子查询的规 ...

  5. mysql sql_safe_updates 不支持子查询的更新。

    考虑到开发人员有时候不小心误更新数据,要求线上库的 MySQL 实例都设置 sql_safe_updates=1 来避免没有索引的 update.delete. 结果有一天开发发现下面的一个SQL 没 ...

  6. 【T-SQL基础】03.子查询

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化. 本系列[T-SQL基础]主要是针对T-SQL基础的总结. [T-SQL基础]01.单表查询-几道sql查询题 ...

  7. SQL Server调优系列基础篇(子查询运算总结)

    前言 前面我们的几篇文章介绍了一系列关于运算符的介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符.有兴 ...

  8. MySQL数据库学习笔记(六)----MySQL多表查询之外键、表连接、子查询、索引

    本章主要内容: 一.外键 二.表连接 三.子查询 四.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复 ...

  9. mysql in 子查询 效率慢 优化(转)

    mysql in 子查询 效率慢 优化(转) 现在的CMS系统.博客系统.BBS等都喜欢使用标签tag作交叉链接,因此我也尝鲜用了下.但用了后发现我想查询某个tag的文章列表时速度很慢,达到5秒之久! ...

随机推荐

  1. Azure Backup (1) 将SQL Server 2012虚拟机中数据库备份到Azure Storage

    <Windows Azure Platform 系列文章目录> 本文介绍的是由国内世纪互联运维的China Azure,相比国外的Global Azure.主要区别是存储账号的DNS地址不 ...

  2. XPATH基础入门资料

    http://www.w3school.com.cn/xpath/xpath_syntax.asp 不错的网址,入门学习资料

  3. C&num;&colon;屏幕显示区域问题

    更改电脑屏幕显示的文字大小后,平面显示区域问题. /// <summary> /// 屏幕显示尺寸 /// </summary> public static Size Revi ...

  4. Codeforces Round &num;353 &lpar;Div&period; 2&rpar; E&period; Trains and Statistic 线段树&plus;dp

    题目链接: http://www.codeforces.com/contest/675/problem/E 题意: 对于第i个站,它与i+1到a[i]的站有路相连,先在求所有站点i到站点j的最短距离之 ...

  5. Enum枚举类&vert;注解Annotation

    Enum枚举类 ①枚举类和普通类的差别: 使用 enum 定义的枚举类默认继承了 java.lang.Enum 类 枚举类的构造器仅仅能使用 private 訪问控制符 枚举类的全部实例必须在枚举类中 ...

  6. 执行mysql脚本

    方法1: mysql -uroot -p123456 -Ddatabasename < sql文件路径 方法2: source 路径全名 \. 路径全名

  7. Linux 环境 Intelij Idea 安装与快捷图标配置

    索引: 目录索引 参看代码 GitHub: intelij-idea.txt 一.Linux (DeepinOS) 环境 1.官网下载 ideaIU-.tar.gz 2.解压 .tar.gz -C ~ ...

  8. python 13 常用模块 一

    一.time模块 1.time.time()获取当前时间戳,返回长整型 2.time.localtime() 获取当地结构化时间,time.gmtime()获取格林尼治时间   一图需要传入匹配格式, ...

  9. http的三次握手四次挥手

    http : 是一种超文本传输协议 传输指的是在客户端和服务器之间进行传输数据 http不仅仅可以传输文本,还可以传输图片.音频.视频等内容 https : 是一种更加安全的传输协议 在普通的传输协议 ...

  10. JSTL 递增序号

    <c:forEach items="${signBusList}" var="sign" varStatus="xh"> ${x ...