oracle 判断一个字段的值是否包含在另一张表中

时间:2021-07-14 13:35:58
例如:
A表
字段(主键)  字段2
1                  abc;def
2                  123;456
B表
字段(主键)  字段2
3                  abcd
4                  456
判断A表字段2以分号隔开的值是否在B表中存在,存在则不记录,反之记录该数据.
例子返回的A表数据
1            abc
1            def
2            123
请教这个sql怎么写啊  

8 个解决方案

#1


判断A表字段2以分号隔开的值是否在B表中存在,存在则不记录,反之记录该数据.
例子返回的A表数据
1            abc
1            def
2            123

没看明白这个逻辑为什么会返回这个数据?

#2


1            def


这个数据,是根据什么规则包含的?

#3


select a.col1,b.col2
from a,b
where instr(a.col2,b.col2)>0;

比较简单一点的是instr,就是上例,不过有缺陷,比如b表字段是ab,而不是abc也会匹配到。
复杂点的是把a表中的字段2全行转列,然后再精确匹配b表字段2

#4


引用 1 楼 xiaoguanzhao 的回复:
判断A表字段2以分号隔开的值是否在B表中存在,存在则不记录,反之记录该数据.
例子返回的A表数据
1            abc
1            def
2            123

没看明白这个逻辑为什么会返回这个数据?



其实就是把A表中字段2的已分号拆开后的值,判断在B表字段2中是否存在

#5


引用 2 楼 wmxcn2000 的回复:
1            def


这个数据,是根据什么规则包含的?


引用 2 楼 wmxcn2000 的回复:
1            def


这个数据,是根据什么规则包含的?


把A表字段2的值以分号隔开然后在判断B表是否存在,不存在的话就记录

#6


参考一下这个,对你有帮助;

http://bbs.csdn.net/topics/392043373

#7


先拆分再匹配。
将a表的1                  abc;def 拆成形如
1 abc
1 def
再关联b表

其实从效率上来将,用存储过程来处理可能会更合适

#8


select aaaa.id,aaaa.str from (
select distinct aaa.id, aaa.str, aaa.flag,count(*) count
  from (select aa.id,
               aa.str str,
               b.str str1,
               case
                 when aa.str = b.str then
                  1
                 else
                  0
               end flag
          from (select a.id, to_char(wm_concat(a.str)) str
                  from (select t.id,
                               case
                                 when instr(t.str, ';') > 0 then
                                  substr(t.str, 1, instr(t.str, ';') - 1)
                               end str,  --如果有分号,则切割分号前半部分字段
                               case
                                 when instr(t.str, ';') > 0 then
                                  substr(t.str,
                                         instr(t.str, ';') + 1,
                                         length(t.str) - instr(t.str, ';')) --切割字段
                               end str1  --如果有分号,则切割分号后半部分字段
                          from (select 1 ID, 'abc;def' str
                                  from dual
                                union all
                                select 2, '123;456' from dual) t) a
                 group by a.id   --进行分号前半部分的行转列
                union
                select a.id, to_char(wm_concat(a.str1)) str
                  from (select t.id,
                               case
                                 when instr(t.str, ';') > 0 then
                                  substr(t.str, 1, instr(t.str, ';') - 1)  
                               end str, --如果有分号,则切割分号前半部分字段
                               case
                                 when instr(t.str, ';') > 0 then
                                  substr(t.str,
                                         instr(t.str, ';') + 1,
                                         length(t.str) - instr(t.str, ';')) --切割字段
                               end str1   --如果有分号,则切割分号后半部分字段
                          from (select 1 ID, 'abc;def' str
                                  from dual
                                union all
                                select 2, '123;456' from dual --测试数据
                                ) t) a
                 group by a.id  --进行分号后半部分的行转列
                
                ) aa
        
          left join
        
         (select 3 ID, 'abcd' str
           from dual
         union all
         select 4, '456' from dual --测试数据
         ) b on 1 = 1  --产生笛卡尔乘积如切割后的字段与B表中相同则标记为1,不同则标记为0
         
         ) aaa
 group by aaa.id, aaa.str, aaa.flag
 ) aaaa where aaaa.flag=0  and aaaa.count=(select count(*) from (select 3 ID, 'abcd' str
           from dual
         union all
         select 4, '456' from dual ))
    --把flga标记为0且在B表中都不存在的记录列出来


貌似写得有点复杂,仅供参考

#1


判断A表字段2以分号隔开的值是否在B表中存在,存在则不记录,反之记录该数据.
例子返回的A表数据
1            abc
1            def
2            123

没看明白这个逻辑为什么会返回这个数据?

#2


1            def


这个数据,是根据什么规则包含的?

#3


select a.col1,b.col2
from a,b
where instr(a.col2,b.col2)>0;

比较简单一点的是instr,就是上例,不过有缺陷,比如b表字段是ab,而不是abc也会匹配到。
复杂点的是把a表中的字段2全行转列,然后再精确匹配b表字段2

#4


引用 1 楼 xiaoguanzhao 的回复:
判断A表字段2以分号隔开的值是否在B表中存在,存在则不记录,反之记录该数据.
例子返回的A表数据
1            abc
1            def
2            123

没看明白这个逻辑为什么会返回这个数据?



其实就是把A表中字段2的已分号拆开后的值,判断在B表字段2中是否存在

#5


引用 2 楼 wmxcn2000 的回复:
1            def


这个数据,是根据什么规则包含的?


引用 2 楼 wmxcn2000 的回复:
1            def


这个数据,是根据什么规则包含的?


把A表字段2的值以分号隔开然后在判断B表是否存在,不存在的话就记录

#6


参考一下这个,对你有帮助;

http://bbs.csdn.net/topics/392043373

#7


先拆分再匹配。
将a表的1                  abc;def 拆成形如
1 abc
1 def
再关联b表

其实从效率上来将,用存储过程来处理可能会更合适

#8


select aaaa.id,aaaa.str from (
select distinct aaa.id, aaa.str, aaa.flag,count(*) count
  from (select aa.id,
               aa.str str,
               b.str str1,
               case
                 when aa.str = b.str then
                  1
                 else
                  0
               end flag
          from (select a.id, to_char(wm_concat(a.str)) str
                  from (select t.id,
                               case
                                 when instr(t.str, ';') > 0 then
                                  substr(t.str, 1, instr(t.str, ';') - 1)
                               end str,  --如果有分号,则切割分号前半部分字段
                               case
                                 when instr(t.str, ';') > 0 then
                                  substr(t.str,
                                         instr(t.str, ';') + 1,
                                         length(t.str) - instr(t.str, ';')) --切割字段
                               end str1  --如果有分号,则切割分号后半部分字段
                          from (select 1 ID, 'abc;def' str
                                  from dual
                                union all
                                select 2, '123;456' from dual) t) a
                 group by a.id   --进行分号前半部分的行转列
                union
                select a.id, to_char(wm_concat(a.str1)) str
                  from (select t.id,
                               case
                                 when instr(t.str, ';') > 0 then
                                  substr(t.str, 1, instr(t.str, ';') - 1)  
                               end str, --如果有分号,则切割分号前半部分字段
                               case
                                 when instr(t.str, ';') > 0 then
                                  substr(t.str,
                                         instr(t.str, ';') + 1,
                                         length(t.str) - instr(t.str, ';')) --切割字段
                               end str1   --如果有分号,则切割分号后半部分字段
                          from (select 1 ID, 'abc;def' str
                                  from dual
                                union all
                                select 2, '123;456' from dual --测试数据
                                ) t) a
                 group by a.id  --进行分号后半部分的行转列
                
                ) aa
        
          left join
        
         (select 3 ID, 'abcd' str
           from dual
         union all
         select 4, '456' from dual --测试数据
         ) b on 1 = 1  --产生笛卡尔乘积如切割后的字段与B表中相同则标记为1,不同则标记为0
         
         ) aaa
 group by aaa.id, aaa.str, aaa.flag
 ) aaaa where aaaa.flag=0  and aaaa.count=(select count(*) from (select 3 ID, 'abcd' str
           from dual
         union all
         select 4, '456' from dual ))
    --把flga标记为0且在B表中都不存在的记录列出来


貌似写得有点复杂,仅供参考