最近我接受了采访,问题出在哪里 假设数据库中有两个表。 表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)
但是他说还有更好的解决方案。我无法提出任何其他更有效的解决方案。如果有的话,获取姓名列表的另一种有效方法是什么?
答案 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),则实际上是上述操作。