获取两个表中都不通用的名称列值列表?

时间:2019-07-08 11:03:56

标签: sql oracle

最近我接受了采访,问题出在哪里 假设数据库中有两个表。 表T1中有一列名为“名称”的列,其他几列 表T2还具有列名“名称”和其他几列

假设表T1在名称列中的值为 [n1,n2,n3,n4,n5] 表T2的“名称”列中的值是 [n2,n4] 然后输出应该是 [n1,n3,n5]作为n2和n4在两个表中都相同

我们需要找到两个表中都不通用的名称列表。

我为他提供的解决方案是以下面的形式使用join

select name from table1 where name not in (select t1.name from table1 t1 join table2 t2 on t1.name=t2.name)
UNION
select name from table2 where name not in (select t1.name from table1 t1 join table2 t2 on t1.name=t2.name)

但是他说还有更好的解决方案。我无法提出任何其他更有效的解决方案。如果有的话,获取姓名列表的另一种有效方法是什么?

8 个答案:

答案 0 :(得分:2)

如果NAME列中没有NULL值,则还有

select distinct(coalesce(a.name, b.name)) name
from table1 a
full join table1 b on a.name = b.name
where a.name is null or b.name is null

(更正了WHERE条件,抱歉...)

答案 1 :(得分:0)

联合表并返回不包含2的值:

create table t1 (
  c1 int
);
create table t2 (
  c1 int
);

insert into t1 values ( 1 );
insert into t1 values ( 3 );

insert into t2 values ( 2 );
insert into t2 values ( 3 );

commit;

select c1 only_in_one_table 
from   (
  select 'T1' t, c1 from t1
  union 
  select 'T2' t, c1 from t2
)
group  by c1
having count(*) <> 2;

ONLY_IN_ONE_TABLE   
                   1 
                   2 

答案 2 :(得分:0)

我不喜欢带有子查询的not in,因为它在使用null值时表现异常。问的人将不得不解释“更好”的含义。您的版本实际上是合理的。

我可能倾向于使用聚合来解决这个问题:

select name
from ((select distinct name, 1 as in_table1, 0 as in_table2
       from table1
      ) union all
      (select distinct name, 0 as in_table1, 0\1 as in_table2
       from table2
      )
     ) t
group by name
having max(in_table1) <> max(in_table2);

在实际情况下,您可能会有一个单独的表,其中包含所有名称。如果是这样:

select n.*
from names n
where (not exists (select 1 from table1 t1 where t1.name = n.name) and
       exists (select 1 from table2 t2 where t2.name = n.name
      ) or
      (exists (select 1 from table1 t1 where t1.name = n.name) and
       not exists (select 1 from table2 t2 where t2.name = n.name
      );

这通常是最快的方法,因为它不涉及任何聚合或重复删除。

答案 3 :(得分:0)

如果要使用SET运算符,请找到以下解决方案:

CREATE TABLE TABLE1(NAME VARCHAR2(100));
CREATE TABLE TABLE2(NAME VARCHAR2(100));
INSERT INTO TABLE1 VALUES('A');
INSERT INTO TABLE1 VALUES('B');
INSERT INTO TABLE1 VALUES('C');
INSERT INTO TABLE2 VALUES('A');
INSERT INTO TABLE2 VALUES('B');
INSERT INTO TABLE2 VALUES('D');


SELECT
    NAME
FROM
    (
        SELECT
            NAME
        FROM
            TABLE1
        UNION
        SELECT
            NAME
        FROM
            TABLE2
    )
WHERE
    NAME NOT IN (
        SELECT
            NAME
        FROM
            TABLE1
            JOIN TABLE2 USING ( NAME )
    );

干杯!

答案 4 :(得分:0)

另一个可能的解决方案:

使用MINUS运算符(这是Oracle对标准EXCEPT的实现)查找第一张表中的内容,而不查找第二张表中的内容。然后与第二个而不是第一个中的那些联合。

(
  select name
  from t1
  minus 
  select name
  from t2
)  
union all
(
  select name
  from t2
  minus 
  select name
  from t1
);

进行以下设置:

create table t1 
(
  name varchar(10)
);
insert into t1 values ('Arthur');
insert into t1 values ('Zaphod');

create table t2 
(
  name varchar(10)
);

insert into t2 values ('Tricia');
insert into t2 values ('Zaphod');

这将返回:

NAME  
------
Arthur
Tricia

答案 5 :(得分:0)

从(从表1选择ID)中选择ID 全部合并 (从表2中选择ID))作为t1 按id进行计数,其中count(id)= 1

答案 6 :(得分:0)

使用基本设置操作,以下查询应该可以工作。

( 从表1中选择名称 全部合并 从表2中选择名称 ) 减去 ( 从表1中选择名称 相交 从表2中选择名称 ) ;

问候 阿卡什(Akash)

答案 7 :(得分:0)

使用FULL OUTER JOIN:

SELECT DISTINCT(COALESCE(t1.NAME, t2.NAME)) AS NAME
  FROM TABLE1 t1
  FULL OUTER JOIN TABLE2 t2
    ON t2.NAME = t1.NAME
  WHERE t1.NAME IS NULL OR
        t2.NAME IS NULL

FULL OUTER JOIN类似于与RIGHT OUTER JOIN结合的LEFT OUTER JOIN-返回第一个表中存在数据但第二​​个表中不存在数据或第二个表但第一个表中不存在数据的行。您可以使用

来获得相同的效果
SELECT t1.NAME
  FROM TABLE1 t1
  LEFT OUTER JOIN TABLE2 t2
    ON t2.NAME = t1.NAME
  WHERE t2.NAME IS NULL
UNION
SELECT t2.NAME
  FROM TABLE1 t1
  RIGHT OUTER JOIN TABLE2 t2
    ON t2.NAME = t1.NAME
  WHERE t1.NAME IS NULL

实际上,如果您使用的数据库不支持FULL OUTER JOIN语法(例如,我上次查看MySQL),则实际上是上述操作。

See this dbfiddle