首页 > 解决方案 > SQL EXCEPT 跨多个列

问题描述

我正在尝试比较两个几乎相同的选择查询;两个查询都从同一个表中输出相同的列。只有单个属性(where foo = 'BAR'vs. where foo <> 'BAR')的条件不同。结果是巨大的,可能只有一些细微的差异。我目前的方法是执行这两个查询,然后将结果放入 Excel 并使用公式来比较两者。乏味和贫穷 - 必须有更好的方法。

如何构建一个单独执行每个选择的查询,然后只显示那些两边都不存在的行?

这是我的查询的简化版本:

-- first query
select a.foo, a.bar, a.moo from abc.mytable a where a.somedetail = 'BAR'
group by a.foo, a.bar, a.moo
order by a.foo, a.bar, a.moo;

-- second query
select a.foo, a.bar, a.moo from abc.mytable a where a.somedetail <> 'BAR'
group by a.foo, a.bar, a.moo
order by a.foo, a.bar, a.moo;

查看这个答案,看起来我需要 EXCEPT 运算符(但在两个方向上,这可能吗?),或者 UNION 或 FULL OUTER JOIN 但对于那些我真的不知道如何设置 WHERE 子句的人匹配两组中的所有列,是的,列中存在差异somedetail

每个数据库只需要执行一次,但性能是一个非常重要的考虑因素,因为数据涵盖数百万行。

标签: sqloracle

解决方案


你不需要group by,所以你可以这样写:

select a.foo, a.bar, a.moo
from abc.mytable a
where a.somedetail = 'BAR'
except
select a.foo, a.bar, a.moo
from abc.mytable a
where a.somedetail <> 'BAR';

鉴于您正在扫描所有数据,您可能会发现group by效果更好:

select a.foo, a.bar, a.moo
from abc.mytable a
group by a.foo, a.bar, a.moo
having sum(case when a.somedetail = 'BAR' then 1 else 0 end) > 0 and
       sum(case when a.somedetail <> 'BAR' then 1 else 0 end) > 0;

如果你有一个索引(foo, bar, moo),Oracle 应该很聪明地在这个查询中使用它。


推荐阅读