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)
在这种情况下,哪个会回归艾伦,弗雷德和史蒂夫.
但这些感觉真的很笨重 - 有没有更有效的方式来接近这个?
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会检测到重复.如果你想要它也是名字,你应该添加name到JOIN.如果您只想成为名字,请name仅加入.此解决方案(使用JOIN)为您提供了灵活性.
顺便说一句,因为你提供的CREATE与INSERT代码,我居然跑他们,上面的代码是完全运行的代码.