如何在不使用集合运算符的情况下在 oracle 中查找不匹配的行并加入 & 还查询特定行的不匹配列名

Posted

技术标签:

【中文标题】如何在不使用集合运算符的情况下在 oracle 中查找不匹配的行并加入 & 还查询特定行的不匹配列名【英文标题】:How to find unmatched rows in oracle without using set operator and join & also Query the unmatched column names for an particular row 【发布时间】:2017-08-29 15:23:04 【问题描述】:

我正在处理两个表 test1 和 test2 我必须在表 test1 中而不是在 test2 中找到匹配的、不匹配的值......反之亦然

然后我必须合并所有查询以获得最终结果。

但是我遇到了不匹配部分的问题。使用 set 运算符,当我将它与 excel 工作表数据进行比较时,我得到了错误的结果集,然后我得到了 15 个额外的行

注意:两个表中没有共同的列

表:test1

a     b        c
2001  abc    john
2008  cab    sam
2002  qwe    mike
2002  asd    samuel
2012  ddd    sammy

表:test2

a      b      c
2001  abc    john
2008  c@b    saam
2009  qwe    mike
2002  asd    samuel
2001  a bc   john

输出:

表 test1 或 test2 中不匹配的行 这里我假设 test2

a        b      c      column_name
2008    c@b    saam      a,b
2009    qwe    mike    null
2001    a bc   john      b

我想要上面的输出,其中包含 table 和 column_names 中的 unmatched rows

Column_names 包含特定行中不匹配的列的名称。

我的查询(使用减号)

Select t2.a, t2.b, t2.c from
(Select a,b,c  from test1 t1
 Minus  
Select  a,b,c  from test2 t2)

对于 column_name,我的逻辑是

Case when t1.a !=  t2.a then 'column a name' 
When t1.b 1= t2.b then 'column b name' 

 *....And so on .....*

但我认为可以在加入我不想要的

的帮助下完成

我正在使用 Oracle 12c。

【问题讨论】:

没有(至少没有一种有效的)方法可以获取您的column_name 逻辑。 这个问题让我问:***.com/questions/45943385/… 作为逆减集的并集没有达到我的预期。 column_name 的概念毫无意义。如果 table1 中的一行在 table2 中没有匹配,这并不意味着有一个或多个列没有(不)匹配。考虑一个简单的例子,每个表中有两列。在第一个中,您有行 (1,'x')。在第二个中,您有行 (1, 'a') 和 (2, 'x')。 table1 中行 (1, 'x') 的哪一列不匹配? (table2 中的哪一行是 table1 中“应该”匹配的行?) @mathguy 那么有没有办法在结果集中获取该不匹配行的列名 我只是说这个概念没有意义,而您是在问“那么有没有办法让...进入结果集中”?你看到这里的不匹配了吗?当两个表都有一个公共的 PRIMARY KEY 列(或列的组合)时,only 的概念才有意义;然后您按主键匹配,您可以看到哪些列不同,或者哪些行(哪些 PK)仅存在于一个表中,但不存在于两个表中。如果没有特定的方法来识别表之间的行,那么整个“不匹配列”的概念就没有意义了。 【参考方案1】:

您只需要使用联合和减号两次。减号只查看第一个表中的记录,而不是第二个表中的记录。要在使用减号时查看不在两者中的表的顺序,请使用联合。

With test1 (A,b,c) as (
SELECT 2001,  'abc',    'john' from dual union all
SELECT 2008,  'cab',    'sam' from dual union all
SELECT 2002,  'qwe',    'mike' from dual union all
SELECT 2002,  'asd',    'samuel' from dual union all
SELECT 2012,  'ddd',    'sammy' from dual),
test2 (a,b,c) as (
SELECT 2001, 'abc',    'john' from dual union all
SELECT 2008, 'c@b',    'saam' from dual union all
SELECT 2009, 'qwe',    'mike' from dual union all
SELECT 2002, 'asd',    'samuel' from dual union all
SELECT 2001, 'a bc',   'john' from dual )
-- ()'s matter here as UNION minus and select all occur at the same level of precedence.  
-- so test1-test2 union test2 minus test1 w/o them!
(Select * from test1 minus Select * from test2)
UNION ALL
(Select * from test2 minus Select * from test1)

--but if you use a cte it works...
With test1 (A,b,c) as (
SELECT 2001,  'abc',    'john' from dual union all--
SELECT 2008,  'cab',    'sam' from dual union all--x
SELECT 2002,  'qwe',    'mike' from dual union all--x
SELECT 2002,  'asd',    'samuel' from dual union all--
SELECT 2012,  'ddd',    'sammy' from dual),--x
test2 (a,b,c) as (
SELECT 2001, 'abc',    'john' from dual union all--
SELECT 2008, 'c@b',    'saam' from dual union all--x
SELECT 2009, 'qwe',    'mike' from dual union all--x
SELECT 2002, 'asd',    'samuel' from dual union all--
SELECT 2001, 'a bc',   'john' from dual ),
cte as (Select * from test1 minus Select * from test2),  --NEEDED
cte2 as (Select * from test2 minus Select * from test1)  --NEEDED
Select * from cte
union 
Select * from cte2;

或者这也可以:

Select * from (
Select Distinct * from test1
UNION ALL
SELECT Distinct * From test2)
Group by A,B,C
having count(*) = 1

使用完全外连接,我们可以得到列名...。

SELECT A.*, B.*, case when coalesce(A.A,0)<>coalesce(B.A,-1) then 'A' end ||','||
                case when coalesce(A.B,'0')<>coalesce(B.B,'-0') then 'B' end ||','||
                case when coalesce(A.C,'0')<>coalesce(B.C,'-0') then 'C' end  as MisMatchOn
FROM test1 A
FULL OUTER JOIN Test2 B
on 1=1 
where length(case when coalesce(A.A,0)<>coalesce(B.A,-1) then 'A' end ||','||
                case when coalesce(A.B,'0')<>coalesce(B.B,'-0') then 'B' end ||','||
                case when coalesce(A.C,'0')<>coalesce(B.C,'-0') then 'C' end)<5
and replace(case when coalesce(A.A,0)<>coalesce(B.A,-1) then 'A' end ||','||
                case when coalesce(A.B,'0')<>coalesce(B.B,'-0') then 'B' end ||','||
                case when coalesce(A.C,'0')<>coalesce(B.C,'-0') then 'C' end,',','') is not null;

【讨论】:

但是有什么办法我也可以获得不匹配的列名吗? 我在玩那个。如果不进行完整的外部联接,我看不到如何获取列名。原因是所有记录都必须与所有记录进行比较,这意味着我们会得到很多需要排除的不匹配项。我添加了一个可能方法的示例,但其中有很多猜测

以上是关于如何在不使用集合运算符的情况下在 oracle 中查找不匹配的行并加入 & 还查询特定行的不匹配列名的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用存储过程的情况下在表函数中返回值 exec?

如何在不进行分组的情况下在Oracle中向SQL结果添加虚拟行

在不使用 Sqoop 的情况下在 HDFS 中加载 Oracle 数据

如何在不使用 java.math.BigInteger 的情况下在 Java 中处理非常大的数字

如何在不使用 Segue 的情况下在单独的 UIViewController 中选择实例变量

如何在不安装的情况下在应用程序中使用 Berkeley DB