Oracle 比较 2 个表之间的数据

Oracle comparing data between 2 tables

提问人:Vikram Daruru 提问时间:11/17/2023 最后编辑:Vikram Daruru 更新时间:11/18/2023 访问量:52

问:

我有 2 张表格,如下所示:

表1:

聚丙烯 CP公司 林努姆
编号:4610-A4N3C-K0235 18961-060 900000021
编号:4610-A4N3C-K0235 22873 900000028
编号:4610-A4N3C-K0235 23282-10 900000038
编号:4610-A4N3C-K0235 23282-10 900000044

表2:

聚丙烯 CP公司 林努姆
编号:4610-A4N3C-K0235 18961-060 900000021
编号:4610-A4N3C-K0235 22873 900000028
编号:4610-A4N3C-K0235 23282-10 900000038
编号:4610-A4N3C-K0235 23282-10 900000044

我正在使用以下查询来比较两个表中的 PP、CP 列并检查 linnum 是否匹配。我在两个表中总共有 126 个条目,并期望输出 126 个条目。

select a.pp,a.cp,a.linnum,b.pp,b.pp,b.linnum,
case when a.pp=b.pp and a.cp=b.cp and a.linnum=b.linnum then 'Y' Else 'N' end matchnomatch
from tt1 a inner join tt2 b
on (a.pp=b.pp and a.cp=b.cp);

输出:

A.PP型 A.CP公司 A.林努姆 乙酰丙烯 B.CP公司 B.林努姆 比赛不匹配
编号:4610-A4N3C-K0235 18961-060 900000021 编号:4610-A4N3C-K0235 18961-060 900000021 Y
编号:4610-A4N3C-K0235 22873 900000028 编号:4610-A4N3C-K0235 22873 900000028 Y
编号:4610-A4N3C-K0235 23282-10 900000038 编号:4610-A4N3C-K0235 23282-10 900000038 Y
编号:4610-A4N3C-K0235 23282-10 900000044 编号:4610-A4N3C-K0235 23282-10 900000038 N
编号:4610-A4N3C-K0235 23282-10 900000038 编号:4610-A4N3C-K0235 23282-10 900000044 N
编号:4610-A4N3C-K0235 23282-10 900000044 编号:4610-A4N3C-K0235 23282-10 900000044 Y

尽管两个表中的所有内容都匹配,但我在 matchnomatch 列中得到了 292 个条目作为输出,甚至 N 作为输出。最好的方法是什么?

我只期待以下输出 预期输出:

A.PP型 A.CP公司 A.林努姆 乙酰丙烯 B.CP公司 B.林努姆 比赛不匹配
编号:4610-A4N3C-K0235 18961-060 900000021 编号:4610-A4N3C-K0235 18961-060 900000021 Y
编号:4610-A4N3C-K0235 22873 900000028 编号:4610-A4N3C-K0235 22873 900000028 Y
编号:4610-A4N3C-K0235 23282-10 900000038 编号:4610-A4N3C-K0235 23282-10 900000038 Y
编号:4610-A4N3C-K0235 23282-10 900000044 编号:4610-A4N3C-K0235 23282-10 900000044 Y

如果 linnum 与 pp 和 cp 匹配不完全匹配,则应给出 N。如何在oracle sql中做到这一点。

Oracle 左联接

评论

1赞 SelVazi 11/17/2023
数据太多了,你能不能分享几行,以便我们可以跟上,以及预期的输出?
1赞 Paul W 11/17/2023
目前尚不清楚你的期望和你得到的是什么。问题是返回了 # 行,还是您看到 Y 和 N 的混合,而您只期望 Y?
2赞 Fat P 11/17/2023
每个表中有 2 行 CP='23282-10'。您的内部联接条件会将所有这些行与另一个表中的记录进行匹配。因此,这些将生成 2 * 2 = 4 行。您需要定义当有多个具有相同 PP 和 CP 的行时,表中的行应如何匹配。

答:

-1赞 gsalem 11/17/2023 #1

关于您的查询的一些评论:

select a.pp,a.cp,a.linnum,b.pp,b.pp,b.linnum,
case when a.pp=b.pp and a.cp=b.cp and a.linnum=b.linnum then 'Y' Else 'N' end matchnomatch
from tt1 a inner join tt2 b
on (a.pp=b.pp and a.cp=b.cp);

它返回的每一行都必须在第 bth 表中具有相同的 pp 和 cp,因此同时显示它们是无用的。在你的案例陈述中比较它们也是无用的。 如果你想让 linnum 相同的行变得恰巧,那么使用这个

select a.pp,a.cp,a.linnum
from tt1 a inner join tt2 b
on (a.pp=b.pp and a.cp=b.cp and a.linnum=b.linnum);
-1赞 MT0 11/17/2023 #2

LEFT JOIN在所有 3 列上,然后根据联接行的存在检查是否在表达式中找到匹配项:CASE

SELECT t1.*,
       CASE WHEN t2.pp IS NOT NULL THEN 'Y' ELSE 'N' END AS matchnomatch
FROM   table1 t1
       LEFT OUTER JOIN table2 t2
       ON     t1.pp = t2.pp
          AND t1.cp = t2.cp
          AND t1.linnum = t2.linnum;

输出:

聚丙烯 CP公司 林努姆 比赛不匹配
编号:4610-A4N3C-K0235 18961-060 900000021 Y
编号:4610-A4N3C-K0235 22873 900000028 Y
编号:4610-A4N3C-K0235 23282-10 900000038 Y
编号:4610-A4N3C-K0235 23282-10 900000044 Y

或者,如果之间有多个匹配项,则仅需要行 from 而没有重复项,则仅选择 from 并用于检查 :table1table1table2table1EXISTStable2

SELECT t1.*,
       CASE WHEN EXISTS (SELECT 1
                         FROM   table2 t2
                         WHERE  t1.pp = t2.pp
                         AND    t1.cp = t2.cp
                         AND    t1.linnum = t2.linnum)
       THEN 'Y'
       ELSE 'N'
       END AS matchnomatch
FROM   table1 t1;

对于示例数据,其输出与上述相同。

小提琴

评论

0赞 SelVazi 11/17/2023
第一个查询应该是 !LEFT JOIN
0赞 MT0 11/18/2023
@SelVazi 谢谢,我会把它放在描述中,只是在查询中输入错误。现已修复。
0赞 Vikram Daruru 11/20/2023
非常感谢@fiddle。第二个查询帮助我获得了我需要的输出
-1赞 Boneist 11/18/2023 #3

与其在 linenum 上连接 - 并假设如果行号不同,它不会影响 pp,cp 组中的顺序(这样,如果您在一个组中有三行,并且在 table1 中行数为 1、2、3,则它最终不会在 table2 中成为 1、5、3) - 用行号标记行并在完全外部连接的连接条件下使用它可以得到什么您想要的,例如:

WITH table1 AS (SELECT '4610-A4N3C-K0235' pp, '18961-060' cp, 900000021 linenum FROM dual UNION ALL
                SELECT '4610-A4N3C-K0235' pp, '18961-060' cp, 900000028 linenum FROM dual UNION ALL
                SELECT '4610-A4N3C-K0235' pp, '18961-060' cp, 900000038 linenum FROM dual UNION ALL
                SELECT '4610-A4N3C-K0235' pp, '18961-060' cp, 900000044 linenum FROM dual),
     table2 AS (SELECT '4610-A4N3C-K0235' pp, '18961-060' cp, 900000021 linenum FROM dual UNION ALL
                SELECT '4610-A4N3C-K0235' pp, '18961-060' cp, 900000028 linenum FROM dual UNION ALL
                SELECT '4610-A4N3C-K0235' pp, '18961-060' cp, 900000038 linenum FROM dual UNION ALL
                SELECT '4610-A4N3C-K0235' pp, '18961-060' cp, 900000044 linenum FROM dual),
         t1 AS (SELECT pp, cp, linenum, row_number() OVER (PARTITION BY pp, cp ORDER BY linenum) rn FROM table1),
         t2 AS (SELECT pp, cp, linenum, row_number() OVER (PARTITION BY pp, cp ORDER BY linenum) rn FROM table2)
SELECT t1.pp,
       t1.cp,
       t1.linenum,
       t2.pp,
       t2.cp,
       t2.linenum,
       CASE WHEN t1.linenum = t2.linenum THEN 'Y' ELSE 'N' END matching
FROM   t1
       FULL OUTER JOIN t2 ON t1.pp = t2.pp AND t1.cp = t2.cp AND t1.rn = t2.rn;