早上到公司,收到一条cocall消息,是某哥们遇到的疑惑,可能很多新手并不知情:

请教个问题
我执行
1. select * from t_htgl_htpswj t where t.c_wjmc = '山西'; 结果是 存在一条记录
2. select * from t_htgl_fj t where t.c_wjmc = '山西'; 结果是不存在记录
3. 为什么执行
select count(*) from t_htgl_htpswj htpswj where htpswj.c_wjmc not in (select fj.c_wjmc from t_htgl_fj fj )
按照 1,2的执行结果,3的结果应该是至少是1才对呀,为什么实际执行结果是0呢。。。。 C_WJMC的类型都是VARCHAR(200)
很诡异的是 第三个查询,我如果用下面这个语句统计查询又是可以查询到结果的。。。。
select count(*) from t_htgl_htpswj htpswj where htpswj.c_wjmc not in (select fj.c_wjmc from t_htgl_fj fj where fj.n_xsxm_htps is not null)
我添加的这个子查询的条件好像和整体查询没有关系呀。。。

对于这个问题,需要了解以下两点内容:
1.null到底是个什么东西?
2.not in是如何执行的,什么原理?
下面看第一点:
1.null到底是个什么东西?我们知道在存储过程中:select a into b from t1 where c='';--如果返回的记录为零,那么会报错,此时实际上返回的就是一个null,一般在前面加一个count的判断再into。
null在oracle中代表什么都不是,空记录,这个地球人都知道,关键是在运算中,null和任何值的算术或者逻辑运算结果都是null,而且它和任何值都不相等,也非不相等,和自身也不相等,如:
select * from t1 where a=null;--查不到正确的记录
select * from t1 where null=null;--查不到记录。因此在判断空与非空时使用is null或者is not null来判断,以下是有个哥们让优化的sql:

..........
union all
select C_BH,N_AJLB,C_AH,C_AJJC,C_AJMC,C_BH_SAR,D_BJRQ,C_BH_CBDW from t_ywgy_hztj_aj where n_ajlb = 202 and C_TBLX <> null union all
select C_BH,N_AJLB,C_AH,C_AJJC,C_AJMC,C_BH_SAR,D_BJRQ,C_BH_CBDW from t_ywgy_hztj_aj where n_ajlb = 302 and C_TBLX <> null ...........

这样写是不对的,会获取不到正确的记录。应该这样写:
select * from t1 where a is null or b is not null;

插播一点,is null和is not null判断都是无法使用索引的,tom的书上有个很不错的提议,就是将null以一个值来代替,如果某列代码值为空,如不妨以-1来代表null,字符的话也可以以其他值(如‘null’)代替,这样在判断的时候可以使用索引。
2.not in 是如何执行的?
先看in是如何执行的:
如:

select * from t where a in(1,2,3);查询等价于:
select * from t where a=1 or a=2 or a=3;

如果条件有null呢?

select * from t where a in(1,2,3,null);等价于:
select * from t where a=1 or a=2 or a=3 or a=null;
--这是没有问题的,一般一样可以得到正确结果,因为a和null不相等,因此null值会被忽略

那么not in呢?

select * from t where a not in(1,2,3);--等价于
select * from t where a !=1 and a!=2 and a!=3;

如果这个条件中有null值呢?

select * from t where a not in(1,2,3,null);--等价于
select * from t where a !=1 and a!=2 and a!=3 and a!=null;

看a!=null,这个条件是不成立的,始终都是false,所以导致整个表达式为false,所以查不到任何记录。

回到开头的问题:

select  count(*) from t_htgl_htpswj htpswj where htpswj.c_wjmc not in (select fj.c_wjmc from t_htgl_fj fj  );

"select fj.c_wjmc from t_htgl_fj fj",这个sql中c_wjmc返回的结果是否包含null值呢?
我们执行以下sql:
select count(*) from t_htgl_fj fj where fj.c_wjmc is null;
----------
COUNT(*)
30
----------
所以,子查询中的c_wjmc存在null值,导致整个where的逻辑运算结果为false,因此没有返回任何结果。
那么为什么

“select count(*) from t_htgl_htpswj htpswj where htpswj.c_wjmc not in (select fj.c_wjmc from t_htgl_fj fj where fj.n_xsxm_htps is not null)”查询就能返回结果呢?

select fj.c_wjmc from t_htgl_fj fj where fj.n_xsxm_htps is not null;--这个查询中c_wjmc有没有空值呢?
执行以下查询:

select count(*) from thims.t_htgl_fj fj where fj.n_xsxm_htps is not null and c_wjmc is null;--n_xsxm_htps为空且c_wjmc也为空的记录:
----------
COUNT(*)
0
----------

这个查询中恰巧n_xsxm_htps is not null将所有的c_wjmc为null的记录过滤掉了,所以子查询中没有null值,所以能查到正确的结果。

结论:在not in的查询中,如果子查询结果中包含null值,将查不到记录,not in无法处理null值。因此可以使用exists,如果非要使用not in,也要保证在子查询中将null值过滤掉。
通常情况下,exists效率要高于in,而且exists可以准确的处理null值(其实是事先过滤掉罢了,不再赘述),关于exists和in的使用场景和区别,见另一篇帖子:

【原创】关于not in的一些事情的更多相关文章

  1. LM-MLC 一种基于完型填空的多标签分类算法

    LM-MLC 一种基于完型填空的多标签分类算法 1 前言 本文主要介绍本人在全球人工智能技术创新大赛[赛道一]设计的一种基于完型填空(模板)的多标签分类算法:LM-MLC,该算法拟合能力很强能感知标签 ...

  2. Django admin美化插件suit应用[原创]

    前言 由于比较懒,自己弄了一个用户验证,没有自己写后台,用了django自带的user认证,并通过admin直接进行管理,但默认的admin并不漂亮,于是使用了这个django-suit插件,效果对比 ...

  3. 【原创】自己动手写工具----XSmartNote [Beta 3.0]

    一.前面的话 在动笔之前,一直很纠结到底要不要继续完成这个工具,因为上次给它码代码还是一年多之前的事情,参考自己动手写工具----XSmartNote [Beta 2.0],这篇博文里,很多园友提出了 ...

  4. 【原创】自己动手写工具----签到器[Beta 2.0]

    一.前面的话 上一篇中基本实现了简单的签到任务,但是不够灵活.在上一篇自己动手写工具----签到器的结尾中,我设想了几个新增功能来提高工具的灵活程度,下面把新增功能点列出来看看: (1)新增其他的进程 ...

  5. 【原创】轻量级移动设备即时通讯技术MobileIMSDK的常见问题解答

    申明:MobileIMSDK 目前为个人原创开源工程且已发布,现整理了一些有关MobileIMSDK的常见的问题,希望对需要的人有用,谢谢.如需与作者交流,见文章底部个人签名处,互相学习. Mobil ...

  6. [原创]cocos2d-x研习录-第三阶 特性之物理引擎

    游戏物理引擎是指在游戏中涉及物理现象的逻辑处理,它用于模拟现实世界的各种物理规律(如赛车碰撞.子弹飞行.物体掉落等),让玩家能够在游戏中有真实的体验. Cocos2D-x中支持Box2D和Chipmu ...

  7. 【原创】loadrunner12.53 录制脚本时 打不开网页或者打开网页慢?

          问题描述: 之前刚装12.5版本时候,用 WebTours测试过,应用程序选择自己本地IE浏览器.exe程序,输入url地址就可以成功录制了 . 但是由于公司网络配置环境改变了(猜测),现 ...

  8. 玩转CSS3,嗨翻WEB前端,CSS3伪类元素详解/深入浅出[原创][5+3时代]

    在我的上一篇博客中, 很多园友提出说对css3"画图"不是很理解, 在跟他们私聊了一段时间以后,加上自己在开始自学css3的时候的疑惑,我觉得大家之所以不是很理解主要是因为对伪元素 ...

  9. html5+css3实现跑动的爱心/动态水滴效果[原创][5+3时代]

    大风起兮云飞扬,安得猛士兮走四方!html5+css3,不学不行. 做web开发已经有好几年了,见证了太多语言的崛起和陨落. 其实作为一个程序员最苦逼的事情莫过于每天要不停的追赶各大公司新出的框架和语 ...

随机推荐

  1. MyEclipse安装TestNG

    1.获取TestNG运行包. (1).直接下载*.jar包并导入项目中. (2).maven下载. http://testng.org/doc/download.html 2.为IDE加载TestNG ...

  2. 利用IOC—— Castle进行对象映射,以及结合Nhibernate访问数据库

    相信很多人对IOC这个概念并不陌生,简而言之其核心就是利用反射来创建对象来实现解耦. 具体这么做解耦的好处是什么,因为鄙人做的项目还不多,所以还没体会到. 但好的项目大概是这样的 就是实现“高内聚,低 ...

  3. PopupWindow实现点击外部不消失

    View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.alert_ip, null); final Po ...

  4. CoordinatorLayout:android之ScrollingActivity

    1.效果图 2.新建SrcollingActivity后生成代码为: <?xml version="1.0" encoding="utf-8"?> ...

  5. Photoshop保存文件时的选项

    以 JPEG 格式存储 您可以使用"存储为"命令以 JPEG (*.jpg) 格式存储 CMYK.RGB 和灰度图像.JPEG 通过有选择地扔掉数据来压缩文件大小.也可以使用&qu ...

  6. JS中let和var的区别

    js中let和var定义变量的区别   let变量之前没见过,刚遇到,探探究竟. 以下转自:http://blog.csdn.net/nfer_zhuang/article/details/48781 ...

  7. BZOJ 1834: [ZJOI2010]network 网络扩容 最小费用流_最大流_残量网络

    对于第一问,跑一遍最大流即可. 对于第二问,在残量网络上的两点间建立边 <u,v>,容量为无限大,费用为扩充费用. 跑一遍最小费用流即可. Code: #include <vecto ...

  8. oracle中nvl函数用法

    1.返回两个字段中非空字段的值,第一个字段非空,返回第一个字段的值,第二个字段值为null,则返回第二个字段的值,如果都为null 则返回null. select nvl(a,b) from tabl ...

  9. [HDU1052]Tian Ji -- The Horse Racing(田忌赛马)

    题目大意:田忌赛马问题,给出田忌和齐威王的马的数量$n$和每匹马的速度$v$,求田忌最多赢齐威王多少钱(赢一局得200,输一局扣200,平局不得不扣). 思路:贪心. 1.若田忌最慢的马可以战胜齐王最 ...

  10. 关于libnmap 的一些应用

    随笔描述 nmap 可以进行端口的扫描,在安全或运维中可以说是一款不错的神奇吧,在大部分LINUX 里面都自带了nmap 这款工具,他不仅仅是端口扫描,自身还提供许多插件可以使用. 官方文档 nmap ...