转至: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. node 图片上传功能

    node 代码: var http = require("http"); var express = require('express') app = express(), for ...

  2. JS计算时间差值

    var d = '2016 04 30 11:28:04'; var currentDate = new Date();//当前时间 var endDate = new Date(d); //结束时间 ...

  3. thymeleaf的使用

    1.导包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp ...

  4. win10 QQ远程协助部分界面点不了

    win10 QQ远程协助部分界面点不了. 把对方电脑的电脑管家全部退出,退出了也不行. 是win10的防火墙?安全策略?

  5. 解决打开visio2013提示windows正在配置的问题

    由于之前装过office2007.也装过2010版本.新安装visio2013就会出现如下情况 解决办法: 主要是要清理完visio2010及之前的那些没用选项 1.在cmd命令下打开regedit注 ...

  6. EOF与子过程返回

        在2000及其以上系统,P处理语句GOTO新增了:EOF系统标签,意思是移动到当前P处理文件的结尾,EOF==END OF FILE的缩写,意为文件结尾,主要表现形式为:GOTO :EOFOR ...

  7. 可视化库-seaborn-单变量绘图(第五天)

    1. sns.distplot 画直方图 import numpy as np import pandas as pd from scipy import stats, integrate impor ...

  8. 第一模块第一章 review

    ---恢复内容开始--- 练习题: 1.简述编译型与解释型语言的区别,且分别列出你知道的那些属于编译型,哪些属于解释型 机器语言:由于计算机内部只能接受二进制代码,因此,用二进制代码0和1描述的指令称 ...

  9. webserive学习记录1-jdk自带webservice

    最近在看webservice有视频,想年后找工作时增加点资本,视频终于看完了,自己又增加了些东西,现在就把视频中学到的和自己发现的东西总结一下. java jdk中自带一个轻量级的webservice ...

  10. go slice和数组的区别

    1.使用方式 数组和slice长的很像,操作方式也都差不多,并且slice包含了数组的基本的操作方式,如下标.range循环,还有一些如len()则是多种类型共用,所以根据操作根本搞不清数组和切片的区 ...