首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Oracle中的NOT HAVING (inverse HAVING)子句with

Oracle中的NOT HAVING (inverse HAVING)子句with
EN

Stack Overflow用户
提问于 2020-02-20 03:20:52
回答 4查看 713关注 0票数 0

我正在尝试使用HAVING子句过滤GROUP BY CUBE的结果。但是,我需要保留不满足条件组合的行。

我凭直觉尝试:

代码语言:javascript
复制
SELECT [...]
FROM [...]
NOT HAVING (flag_1 = 1 AND flag_2 = 1 AND flag_3 = 1)
GROUP BY CUBE [...]

遗憾的是,甲骨文没有将NOT HAVING识别为有效语法。

从数学的角度来看,反转每个单独的条件并不会产生相同的结果:

HAVING (flag_1 != 1 AND flag_2 != 1 AND flag_3 != 1)

如何实现NOT HAVING的逻辑等价物?

注意:我发现了一个与之相关的现有问题,但它特定于Microsoft Access,并且目标不同,因此出现了这个新问题。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-02-20 03:44:59

HAVING子句的数学逆要求您将and更改为OR and,如果列可以为空,也需要null-check。

例如(如果可能为空):

代码语言:javascript
复制
HAVING (nvl(flag_1,1) != 1 OR NVL(flag_2,1) != 1 OR NVL(flag_3,1) != 1) 
票数 3
EN

Stack Overflow用户

发布于 2020-02-20 04:05:38

我认为最简单的解决方案就是将其更改为HAVING NOT ...

代码语言:javascript
复制
SELECT [...]
FROM [...]
HAVING NOT (flag_1 = 1 AND flag_2 = 1 AND flag_3 = 1)
GROUP BY CUBE [...]

但我经常发现NOT (...)不直观;作为替代方案,@MichaelBroughton的答案解释了如何将逻辑从NOT (x AND y)反转到NOT x OR NOT y

票数 3
EN

Stack Overflow用户

发布于 2020-02-20 04:07:34

这与Michael Broughton的答案相同,我不想重复,但我认为它可以更清楚。如果他想在他的回答中加入任何这一点,我很乐意删除这一条。

要确定NOT (boolean_expression)的逻辑等价物,可以应用德摩根定律。请参阅:https://en.wikipedia.org/wiki/De

基本上,您颠倒了每个术语的逻辑,并将所有and更改为OR,将所有OR更改为and。所以,

代码语言:javascript
复制
NOT (A AND B AND C) ==> (NOT A OR NOT B OR NOT C)

但您也需要跟踪空值。下面是这个过程:

从..开始。

代码语言:javascript
复制
HAVING NOT (flag_1 = 1 AND flag_2 = 1 AND flag_3 = 1)

首先,添加关于起始表达式中存在的NULL的隐式假设。例如,如果是flag_1=1,那么它当然不是NULL。

代码语言:javascript
复制
HAVING NOT (flag_1 = 1 AND flag_1 IS NOT NULL 
        AND flag_2 = 1 AND flag_2 IS NOT NULL 
        AND flag_3 = 1 AND flag_3 IS NOT NULL)

现在,应用德摩根定律的第一部分,并颠倒每一项的逻辑。所以,e,g.,flag_1 = 1变成了flag_1 != 1..。

代码语言:javascript
复制
HAVING (flag_1 != 1 AND flag_1 IS NULL 
    AND flag_2 != 1 AND flag_2 IS NULL 
    AND flag_3 != 1 AND flag_3 IS NULL)

最后,应用德摩根定律的第二部分,切换所有and ->OR,反之亦然。

代码语言:javascript
复制
HAVING (flag_1 != 1 OR flag_1 IS NULL 
     OR flag_2 != 1 OR flag_2 IS NULL 
     OR flag_3 != 1 OR flag_3 IS NULL)

这就是你的答案。

只使用NOT (flag_1 = 1 AND flag_2 = 1 AND flag_3 = 1)如何?

这不起作用,因为它不能像预期的那样处理空值。在Oracle中,任何与null的比较都是false。所以,

代码语言:javascript
复制
    (1 = NULL) ... false
NOT (1 = NULL) ... also false

因此,flag_1flag_2都等于1但flag_3为null的行将不会显示在结果中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60307728

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档