转至: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. 文件查找find命令

    find命令总结: 常用选项: -name 查找/etc目录下以conf结尾的文件 find /etc -name '*conf' -iname 查找当前目录下文件名为aa的文件,不区分大小写 fin ...

  2. python3.5过滤网址和图片的函数自己亲测可用

    def has_replace(tag): #过滤网址 real=re.sub(r'<a\shref=.+</a>', '',tag.decode(), count=0, flags ...

  3. elk6.22

    启动错误: 参考网站:https://blog.csdn.net/feinifi/article/details/73633235?utm_source=itdadao&utm_medium= ...

  4. HTML5 Canvas ( 图片填充样式 ) fillStyle, createPattern

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. Simple2D-18(音乐播放器)使用 bass 音频库

    BASS 简介 BASS是一个在多个平台上用于软件的音频库.其目的是为开发人员提供功能强大且高效的示例流(MP3,MP2,MP1,OGG,WAV,AIFF),MOD 音乐(XM,IT,S3M,MOD ...

  6. XSS学习小结

    一.什么是XSS? XSS全称是Cross Site Scripting即跨站脚本,当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就发生了. 这里我们主要注 ...

  7. CSS3 弹性盒模型 box-flex

    说明:本文档兼容性测试基础环境为:windows系统:IE6-IE10, Firefox6.0, Chrome13.0, Safari5.1, Opera11.51 语法: box-flex:< ...

  8. spring中作用域的问题

    在一般情况下:我们登录系统时,第一次登录当用户名或密码输入错误,在登录页面给出错误原因,当我们再刷新登录页面,应该是首次登录系统的页面(这时就不应该再给出出错提示),这时我们就应该想到错误提示信息到底 ...

  9. IntelliJ IDEA project module

    在IDEA 创建一个project,目录结构是这样的:在project下创建一个module之后目录结构是这样的: 简单的概括如下: IntelliJ系中的 Project  相当于Eclipse系中 ...

  10. Layouts

    [Layouts] Each layout file must contain exactly one root element, which must be a View or ViewGroup ...