SQL选择使用Except和UNION All的问题

时间:2014-01-24 20:47:10

标签: sql sql-server

Select *
From (
Select a
    Except
Select b
) x

UNION ALL

Select *
From (
Select b
    Except
Select a
) y

此sql语句返回极其错误的数据量。如果Select a返回一百万,那么整个语句如何返回100,000?在这种情况下,选择b包含互斥数据,因此除了。之外不应该消除。

2 个答案:

答案 0 :(得分:1)

正如评论中所述,EXCEPT根据 this 执行隐式DISTINCT,并且UNION ALL中的ALL无法重新创建重复项。因此,如果您想保留重复项,则无法使用您的方法。

由于您希望获取其中一个表ab中包含的数据,而不是两者中的数据,因此更有效的方法是实现以下目标(我是假设表格中有idc列,其中id是主键,因为您没有说明任何列名称):

SELECT CASE WHEN a.id IS NULL THEN 'from b' ELSE 'from a' END as source_table
      ,coalesce(a.id, b.id) as id
      ,coalesce(a.c, b.c) as c
  FROM a
       FULL OUTER JOIN b ON a.id = b.id AND a.c = b.c -- use all columns of both tables here!
 WHERE a.id IS NULL OR b.id IS NULL

这使用FULL OUTER JOIN,通过WHERE条件排除匹配记录,因为主键不能为空,除非它来自OUTER侧。 如果您的表没有主键 - 这仍然是不好的做法 - 您必须检查NULL的所有列,而不仅仅是一个主键列。

如果您的记录完全由NULL组成,则此方法不起作用。 然后你可以使用类似于原始方法的方法,只需使用

SELECT ...
 FROM a
WHERE NOT EXISTS (SELECT 1 FROM b WHERE <join by all columns>)

UNION ALL

SELECT ...
 FROM b
WHERE NOT EXISTS (SELECT 1 FROM a WHERE <join by all columns>)

答案 1 :(得分:0)

如果您尝试获取一个表中的任何数据而不是另一个表中的任何数据,我将尝试类似以下内容:

select id, 'table a data not in b' from a where id not in (select id from b)
union
select id, 'table b data not in a' from b where id not in (select id from a)