选择仅出现在两个表之一中的数据的最佳方法是什么?

Dib*_*tar 5 sql sql-server select sql-server-2005

如果我有两个这样的表:

CREATE TABLE #table1 (id INT, name VARCHAR(10))
INSERT INTO #table1 VALUES (1,'John')
INSERT INTO #table1 VALUES (2,'Alan')
INSERT INTO #table1 VALUES (3,'Dave')
INSERT INTO #table1 VALUES (4,'Fred')
CREATE TABLE #table2 (id INT, name VARCHAR(10))
INSERT INTO #table2 VALUES (1,'John')
INSERT INTO #table2 VALUES (3,'Dave')
INSERT INTO #table2 VALUES (5,'Steve')
Run Code Online (Sandbox Code Playgroud)

我希望看到所有行只出现在其中一个表中,最好的方法是什么?

我能想到的是:

SELECT * from #table1 except SELECT * FROM #table2
UNION
SELECT * from #table2 except SELECT * FROM #table1
Run Code Online (Sandbox Code Playgroud)

或者类似的东西:

SELECT id,MAX(name) as name  FROM
(
SELECT *,1 as count from #table1 UNION ALL
SELECT *,1 as count from #table2
) data 
group by id
HAVING SUM(count) =1
Run Code Online (Sandbox Code Playgroud)

在这种情况下,哪个会回归艾伦,弗雷德和史蒂夫.

但这些感觉真的很笨重 - 有没有更有效的方式来接近这个?

Adr*_*iro 6

select coalesce(t1.id, t2.id)     id,
       coalesce(t1.name, t2.name) name
from   #table1 t1
       full outer join #table2 t2
         on t1.id = t2.id
where  t1.id is null
        or t2.id is null  
Run Code Online (Sandbox Code Playgroud)

完整的外连接保证了连接两侧的记录.无论双方都没有的记录(你正在寻找的记录)都会NULL在一方或另一方面.这就是我们过滤的原因NULL.

COALESCE是为了保证NULL将显示非值.

最后,值得强调的是ID会检测到重复.如果你想要它也是名字,你应该添加nameJOIN.如果您只想成为名字,请name仅加入.此解决方案(使用JOIN)为您提供了灵活性.

顺便说一句,因为你提供的CREATEINSERT代码,我居然跑他们,上面的代码是完全运行的代码.