• A表和B表通过ID1和ID2关联,怎么样才能查出来A表中不在B表中的数据?


    今天同事提出了一个问题

    条件:A表和B表通过ID1和ID2关联
    目标:怎么样才能查出来A表中不在B表中的数据?

    形象点,我把这两个表创建出来。

    create table A
    (
      id1   VARCHAR2(100),
      id2   VARCHAR2(100),
      infoA VARCHAR2(100),
      onlyA VARCHAR2(100)
    );
    create table B
    (
      id1   VARCHAR2(100),
      id2   VARCHAR2(100),
      infoB VARCHAR2(100),
      onlyB VARCHAR2(100)
    );

    然后填入一些数据,为了方便辨识,同时故意留下一些空值作为特殊情况,在onlyA、onlyB字段手工标识出这个id1、id2是否只在A表或者B表出现

     插入的数据如下

    prompt Importing table A...
    set feedback off
    set define off
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('1', '001', 'A信息1', 'both');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('1', '002', 'A信息2', 'yes');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('1', '003', 'A信息3', 'yes');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('2', '001', 'A信息4', 'both');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('2', '002', 'A信息5', 'both');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('2', '003', 'A信息6', 'both');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('3', '001', 'A信息7', 'yes');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('3', null, 'A信息8', 'both');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('4', '003', 'A信息9', 'yes');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values (null, '001', 'A信息10', 'both');
    
    insert into A (ID1, ID2, INFOA, ONLYA)
    values ('5', null, 'A信息11', 'yes');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values ('1', '001', '有对照', 'both');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values ('1', '004', 'nothing', 'yes');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values ('1', null, 'nothing', 'yes');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values ('2', '001', '有对照', 'both');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values ('2', '002', '有对照', 'both');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values ('2', '003', '有对照', 'both');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values ('3', null, '有对照', 'both');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values (null, '001', '有对照', 'both');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values ('6', '001', 'nothing', 'yes');
    
    insert into B (ID1, ID2, INFOB, ONLYB)
    values (null, '007', 'nothing', 'yes');
    
    prompt Done.

    同事们给出方案若干个:

    1、把这两个字段拼成一个,然后用not in

    select id1,id2,infoA,id1||id2 as tempA,onlyA from a where id1||id2 not in (select id1||id2 as TempB from B)

     结果5条,符合预期。

    但这个方法的问题是:id1和id2的编码形式是有明显区别的,如果都是三位的数字,那么新字段tempA、tempB该加个下划线或者符号进行区隔

    2、使用(字段1,字段2)这种对象进行比较

    select id1,id2,infoA,onlyA from a where (id1,id2) not in (select id1,id2 from b ) order by id1,id2

     这样的结果很奇怪,只有一条,丢掉了4条,分析其中原因,我们把其中的not 去掉

    select id1,id2,infoA,onlyA from a where (id1,id2)  in (select id1,id2 from b ) order by id1,id2

    这里的both也没有列全,丢掉了两条,这两条是null,001和3,null  

    也就是这种用法会因为id1=1,3内容的id2包含null而被滤掉,id1=5的本身id2就是null也被滤掉,最终只能展示1条符合条件的内容,如下图

     也就是这种描述方法会造成空字段会被滤掉,丢结果,但也是有条件的

    (1)在业务数据中,id1和id2数据合法性可以保证不含空字符串的情况,(如果含空格也不会造成丢数据,只有null会丢)

    (2)可以改造一下后使用,将null值进行转换,然后使用

    select id1,id2,infoA,onlyA from a where (nvl(id1,' '),nvl(id2,' ')) not in (select nvl(id1,' '),nvl(id2,' ') from b ) order by id1,id2

    其他方案1

    因为只筛选id1,造成有漏项有多项

    select a.id1,a.id2,a.infoa,a.onlya 
    from  a 
    where a.id1 not in 
          (select a.id1 from  a inner join  b on a.id1=b.id1 and a.id2=b.id2)

    其他方案2

    select * from A not in (select * from a join b on xxx=xxx)

    有兴趣的朋友可以试一下

  • 相关阅读:
    angularJS
    WebSocket通信协议
    重写ajax方法实现异步请求session过期时跳转登录页面
    npm(cnpm)介绍(安装gulp)
    grunt安装与配置
    前端学习之jquery
    前端基础之CSS
    前端基础html
    激活
    socket 网络通信(基于tcp协议)以及粘包解决方案
  • 原文地址:https://www.cnblogs.com/adamgq/p/12558937.html
Copyright © 2020-2023  润新知