SQL从两个具有匹配数据的表中返回列名

时间:2018-05-17 19:26:22

标签: sql oracle oracle11g

我正在研究数据验证项目。我有2个表(如下所示),我应该运行一个查询,查询应返回Table1.P1和Table2.P1匹配,Table1.P3和Table2.P3匹配。

+++++++++++++++++++++++++++++++        +++++++++++++++++++++++++++++++
+            TABLE1           +        +           TABLE2            +
+---------+---------+---------+        +---------+---------+---------+
| P1      | P2      | P3      |        + P1      | P2      | P3      |
+---------+---------+---------+        +---------+---------+---------+
| A       | 1A      | AA      |        | A       | 1A      | AA      |
| B       | 2A      | BB      |        | B       | 2A      | BB      |
| C       | 3A      | CC      |        | C       | 3A      | CC      |
| D       | 4A      | DD      |        | D       | 4B      | DD      |
| E       | 5A      | EE      |        | E       | 5B      | EE      |
+---------+---------+---------+        +---------+---------+---------+


+      output      +           
+---------+--------+        
| Table   |column  |
|Name     |name    |
+---------+---------
| Tabl1   | P1     | 
| Tabl2   | P3     | 
+------------------+        

我的查询应该返回 匹配列P1和P3My查询应该返回 匹配列P1和P3

预期产出:

表名

3 个答案:

答案 0 :(得分:1)

您知道,如果您没有太多数据(即数据适合varchar列),那么您可以使用listagg()

select (case when t1.p1list = t2.p1list then 'same' end) as p1,
       (case when t1.p2list = t2.p2list then 'same' end) as p2,
       (case when t1.p3list = t2.p3list then 'same' end) as p3       
from (select listagg(p1, ',') within group (order by p1) as p1list,
             listagg(p2, ',') within group (order by p2) as p2list,
             listagg(p3, ',') within group (order by p3) as p3list
      from table1
     ) t1 cross join
     (select listagg(p1, ',') within group (order by p1) as p1list,
             listagg(p2, ',') within group (order by p2) as p2list,
             listagg(p3, ',') within group (order by p3) as p3list
      from table2
     ) t2

答案 1 :(得分:0)

我认为您似乎想要exists

select t1.*
from tabel1 t1
where exists (select 1 from table2 t2 where t2.p1 = t1.p1);
or
. . . 
where exists (select 1 from table2 t2 where t2.p3 = t1.p3);

如果是这样,那么只需将subquery修改为

即可
where exists (select 1 from table2 t2 where t2.p1 = t1.p1 and t2.p3 = t1.p3);

答案 2 :(得分:0)

我不知道如何很好地在SQL中执行它,所以我将使用普通和愚蠢的PL / SQL。看看,如果您觉得它有用,请使用它。

测试用例:

SQL> create table table1
  2  (p1 varchar2(10),
  3   p2 varchar2(10),
  4   p3 varchar2(10));

Table created.

SQL> create table table2
  2  (p1 varchar2(10),
  3   p2 varchar2(10),
  4   p3 varchar2(10));

Table created.

SQL> insert into table1
  2    select 'A', '1A', 'AA' from dual union
  3    select 'B', '2A', 'BB' from dual union
  4    select 'D', '4A', 'DD' from dual;

3 rows created.

SQL> insert into table2
  2    select 'A', '1A', 'AA' from dual union
  3    select 'B', '2A', 'BB' from dual union
  4    select 'D', '4B', 'DD' from dual;

3 rows created.

SQL>

检查两列是否匹配的过程。可能它可以用动态方式编写,使用循环通过USER_TAB_COLUMNS,但我现在不打算这样做 - 如有必要,我可能会这样做。或者,更好的是,自己动手。

正如我所说:平淡而愚蠢:

  • 比较两个表中的行数
  • intersect应返回所有行
  • 减去不应该返回任何内容

我只比较了前两列(P1和P2)。

SQL> create or replace procedure p_match as
  2    l_cnt_1     number;
  3    l_cnt_2     number;
  4    l_intersect number;
  5    l_minus_12  number;
  6    l_minus_21  number;
  7  begin
  8    -- Column P1
  9    select count(*) into l_cnt_1 from table1;
 10    select count(*) into l_cnt_2 from table2;
 11
 12    select count(*) into l_intersect
 13    from (select p1 from table1 intersect select p1 from table2);
 14
 15    select count(*) into l_minus_12
 16    from (select p1 from table1 minus select p1 from table2);
 17
 18    select count(*) into l_minus_21
 19    from (select p1 from table2 minus select p1 from table1);
 20
 21    if l_cnt_1 = l_cnt_2 and
 22       l_intersect = l_cnt_1 and
 23       l_minus_12 = 0 and
 24       l_minus_21 = 0
 25    then
 26       dbms_output.put_line('Column P1 matches');
 27    else
 28       dbms_output.put_line('Column P1 does not match');
 29    end if;
 30
 31    -- Column P2
 32
 33    select count(*) into l_cnt_1 from table1;
 34    select count(*) into l_cnt_2 from table2;
 35
 36    select count(*) into l_intersect
 37    from (select p2 from table1 intersect select p2 from table2);
 38
 39    select count(*) into l_minus_12
 40    from (select p2 from table1 minus select p2 from table2);
 41
 42    select count(*) into l_minus_21
 43    from (select p2 from table2 minus select p2 from table1);
 44
 45    if l_cnt_1 = l_cnt_2 and
 46       l_intersect = l_cnt_1 and
 47       l_minus_12 = 0 and
 48       l_minus_21 = 0
 49    then
 50       dbms_output.put_line('Column P2 matches');
 51    else
 52       dbms_output.put_line('Column P2 does not match');
 53    end if;
 54  end;
 55  /

Procedure created.

SQL> set serveroutput on;
SQL> begin
  2    p_match;
  3  end;
  4  /
Column P1 matches
Column P2 does not match

PL/SQL procedure successfully completed.

SQL>