SubQueries和Group Functions可能存在Oracle-Bug

ber*_*ner 8 sql oracle

任何人都可以解释为什么以下查询返回两行而不只是一行?

SELECT *
  FROM (SELECT 'ASDF' c1, MAX (SUM (1)) c2
          FROM DUAL
         GROUP BY dummy
        UNION
        SELECT 'JKLÖ' c1, 1 c2
          FROM DUAL)
 WHERE c1 != 'ASDF';

--another Version with the same wrong result:
SELECT *
  FROM (SELECT 1 c1, MAX (SUM (1)) c2
          FROM DUAL
         GROUP BY dummy
        UNION all
        SELECT 2 c1, 1 c2
          FROM DUAL)
 WHERE c1 != 1;
Run Code Online (Sandbox Code Playgroud)

Oracle提供两行是否正确?在我看来,c1 = ASDF的行不应该在结果中.

这是第一个查询结果的屏幕截图:

在此输入图像描述

我在以下版本上测试了它,总是得到相同的结果:

  • Oracle Database 11g企业版11.2.0.3.0版 - 64位生产
  • Oracle Database 12c企业版12.1.0.2.0版 - 64位生产

小智 1

它看起来绝对像一个错误。

我真的不知道如何阅读解释计划,但就是这样。在我看来,谓词已被推送到仅一个 UNION 成员,并且已转换为“NULL IS NOT NULL”,这非常奇怪。

请注意,字符串可以更改为“a”和“b”(因此我们不使用特殊字符),UNION 和 UNION ALL 会产生相同的错误,并且该错误似乎是由 MAX(SUM(1) 触发的) 在第一个分支;只需将其替换为 NULL 或其他“简单”的内容,甚至使用 SUM(1) (不带 MAX)即可使查询正常工作。

添加:奇怪的是,如果我更改MAX(SUM(1))MAX(1)or SUM(1),或者如果我只是将其更改为文字 number 1,则查询可以正常工作 - 但解释计划仍然显示相同的奇怪谓词,“NULL IS NOT NULL”。因此,问题似乎在于谓词没有被推送到并集的两个分支,而不是谓词转换。(甚至这也不能解释为什么c2出现NULL在结果集中的额外行中。)更多添加(请参阅下面的评论) - 事实证明,谓词被推送到 UNION 的两个分支,而这正是导致问题(正如尼古拉斯在他的回答中解释的那样)。

Plan hash value: 1682090214

-------------------------------------------------------------------------------
| Id  | Operation              | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |      |     2 |    32 |     2   (0)| 00:00:01 |
|   1 |  VIEW                  |      |     2 |    32 |     2   (0)| 00:00:01 |
|   2 |   UNION-ALL            |      |       |       |            |          |
|   3 |    SORT AGGREGATE      |      |     1 |     2 |            |          |
|   4 |     HASH GROUP BY      |      |     1 |     2 |            |          |
|*  5 |      FILTER            |      |       |       |            |          |
|   6 |       TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)| 00:00:01 |
|   7 |    FAST DUAL           |      |     1 |       |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - filter(NULL IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)

  • @mathguy @AlexPoole 另一个怪癖是当你运行“SELECT * FROM (SELECT 1 c1, MAX (SUM (1)) c2 FROM DUAL WHERE NULL IS NOT NULL GROUP BY dummy);”与“SELECT 1”时得到不同的结果c1, MAX (SUM (1)) c2 FROM DUAL WHERE IS NOT NULL GROUP BY dummy;`。过滤步骤在前者中最后完成,在后者中更早完成(至少在 11.2.0.4 中)。WTF,优化器?!*{;-) (2认同)