求助 <> 和 not in的问题

like30597312_1 2013-03-06 08:59:31
表数据如下:
--------------------------------------------------------------
ID NAME ADDR ROWID
1 1 test addr1 AAARGiAAEAAAAA+AAA
2 1 test addr2 AAARGiAAEAAAAA/AAA
3 1 test addr3 AAARGiAAEAAAAA/AAB
4 2 gogogo addr1 AAARGiAAEAAAAA+AAB
5 2 gogogo addr2 AAARGiAAEAAAAA/AAC
6 3 aaaaaf bbbbbb AAARGiAAEAAAAA+AAC
--------------------------------------------------------------
现在想删除重复记录。重复列为ID和NAME(测试用,无主键)

思路:获得全部重复记录,分组并取得最小rowid,删除其他rowid的行
=================================================================
SQL1:
select t.*, rowid
from emp t
where t.rowid not in (select min(rowid)
from emp e
where e.id = t.id
and e.name = t.name
group by e.id, e.name
having count(*)>1)

查询结果如下:
ID NAME ADDR ROWID
1 3 aaaaaf bbbbbb AAARGiAAEAAAAA+AAC
2 1 test addr2 AAARGiAAEAAAAA/AAA
3 1 test addr3 AAARGiAAEAAAAA/AAB
4 2 gogogo addr2 AAARGiAAEAAAAA/AAC
--------------------------------------------------------------
SQL2:
select t.*, rowid
from emp t
where t.rowid <> (select min(rowid)
from emp e
where e.id = t.id
and e.name = t.name
group by e.id, e.name
having count(*)>1)
查询结果如下:

ID NAME ADDR ROWID
1 1 test addr2 AAARGiAAEAAAAA/AAA
2 1 test addr3 AAARGiAAEAAAAA/AAB
3 2 gogogo addr2 AAARGiAAEAAAAA/AAC
--------------------------------------------------------------
问题:为何SQL1,2取得结果不同,跪求原理。望大神告知。
...全文
311 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
Cryking 2013-03-07
  • 打赏
  • 举报
回复
NOT IN 和<> 不能直接转换的,你这里要么子查询就是一条数据,要么就是NULL,如果有多行数据<>这个会报错的. 是不是你第一个查询到第二个查询间有删除了数据呢? 或者你先执行一下子查询看一下结果
tonypingge 2013-03-07
  • 打赏
  • 举报
回复
搜一下 null值的讨论贴. 类似 = > < <>这种比较符号跟null会产生什么结果.
like30597312_1 2013-03-07
  • 打赏
  • 举报
回复
引用 4 楼 funnyone 的回复:
引用 3 楼 like30597312_1 的回复:引用 1 楼 funnyone 的回复:第一个sql 根据执行计划 会装换为 SQL code?1234567from emp twhere not exists (select 1 from emp e where e.……
再次感谢,但是,我努力的分析了你的答复,断句太难了。。。
funnyone 2013-03-07
  • 打赏
  • 举报
回复
引用 3 楼 like30597312_1 的回复:
引用 1 楼 funnyone 的回复:第一个sql 根据执行计划 会装换为 SQL code?1234567from emp twhere not exists (select 1 from emp e where e.id = t.id ……
<>就是直接循环用的<>比较 如果不存在 <>min(rowid) 这很明显啦 即使min(rowid)为空 也<> 也是假 filter false 不查询出来 前面说是真错啦 Null和任何值 任何比较都是 null
like30597312_1 2013-03-07
  • 打赏
  • 举报
回复
引用 1 楼 funnyone 的回复:
第一个sql 根据执行计划 会装换为 SQL code?1234567from emp twhere not exists (select 1 from emp e where e.id = t.id and e.name =……
感谢回复。 关于<>的回复,我不是很理解。可否详细说明下?
like30597312_1 2013-03-07
  • 打赏
  • 举报
回复
表结构如下,测试数据见顶楼。 ------------------------------- Name Type Nullable Default Storage Comments ID NUMBER N NAME VARCHAR2(100) Y ADDR VARCHAR2(200) Y
Cryking 2013-03-07
  • 打赏
  • 举报
回复
把表结构和测试数据发出来看看
like30597312_1 2013-03-07
  • 打赏
  • 举报
回复
这个子查询返回的要么是一行,要么是NULL。 另外,对于SQL2的问题我明白了:当主查询循环到aaaaaf这条记录时,子查询返回的结果是NULL。 判断rowid <> NULL,则返回unknown,所以aaaaaf不会添加的结果集中。 让我困惑的是SQL1, 也就是not in NULL 为何会将结果添加到结果集中,还是不能用SQL2的方式去解析SQL1? 有大神知道么?继续跪求原理。。。
like30597312_1 2013-03-07
  • 打赏
  • 举报
回复
引用 7 楼 edcvf3 的回复:
NOT IN 和<> 不能直接转换的,你这里要么子查询就是一条数据,要么就是NULL,如果有多行数据<>这个会报错的. 是不是你第一个查询到第二个查询间有删除了数据呢? 或者你先执行一下子查询看一下结果
这个问题的子查询返回的记录永远都是一行。不会出现多行的情况。
funnyone 2013-03-06
  • 打赏
  • 举报
回复
贴下执行计划 第一个



第2个
funnyone 2013-03-06
  • 打赏
  • 举报
回复
第一个sql 根据执行计划 会装换为

from   emp t
where   not exists (select 1
                      from   emp e
                      where  e.id = t.id
                      and    e.name = t.name
                      group by e.id, e.name
                      having min(rowid)=t.rowid and count(*)>1);
当遇到唯一的时候 count(*)>1 永远为假 所以唯一的值也会查询出来 第2 个是使用<> 比较 即使不存在 是<>null 也是真

17,086

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧