我有两个表都包含id(primary key)
,contact_id
和name
。
我想找出两个表之间的差异。因此,如果table A
中的一条记录与table B
不同,则sql查询应该找到它。例如,在下面的代码中,('2','test2')
没有出现在表B中。因此,记录('2','test2')
是两个表之间的差异。但是,我们可能会遇到相反的情况,例如table B
但table A
中出现一条记录。或者两个表中的记录contact_id
可能相同,但name
字段可能不同。在这种情况下,还应返回不同的记录。我已经这样做了,但它似乎并不适用于所有情况。如何让它适用于所有情况?
CREATE TABLE A
(
id int auto_increment primary key,
contact_id int(20),
name varchar(20)
);
CREATE TABLE B
(
id int auto_increment primary key,
contact_id int(20),
name varchar(20)
);
INSERT INTO A
(contact_id,name)
VALUES
('1','test1'),
('2','test2');
INSERT INTO B
(contact_id,name)
VALUES
('1','test1');
查询:
SELECT * FROM A
EXCEPT
SELECT * FROM B
UNION ALL
SELECT * FROM B
EXCEPT
SELECT * FROM A
这是sqlfiddle: http://sqlfiddle.com/#!5/f7f45/9 并在弹出屏幕中选择取消。
答案 0 :(得分:1)
左边加入a到b,其中b为null,得到什么,但不是b,左边的连接b到a,其中a为空,得到b中的什么而不是a。
select 'in a but not b', a.*
from a left join b on a.contact_id = b.contact_ID
where b.contact_ID is null
union all
select'in b but not a', b.*
from b left join a on a.contact_id = b.contact_ID
where a.contact_ID is null
我在一个字段中表示记录的起源,因为它在联合结果中不会显而易见。如果你感兴趣,第三个查询检查记录在a和b中的位置,但是ID有不同的值......同样的想法,只是内连接:
select a.*,b.*
from a inner join b on a.contact_id = b.contact_ID
where a.name <> b.name
答案 1 :(得分:1)
EXCEPT绑定不比UNION ALL强(并且缩进查询不会改变它),因此数据库将在第二个EXCEPT之前执行UNION ALL。
您必须将两个EXCEPT查询移动到子查询中,以确保最后执行UNION ALL:
SELECT * FROM (SELECT * FROM A
EXCEPT
SELECT * FROM B)
UNION ALL
SELECT * FROM (SELECT * FROM B
EXCEPT
SELECT * FROM A)