任何人都可以解释为什么以下查询返回两行而不只是一行?
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;
Oracle提供两行是否正确?在我看来,c1 = ASDF的行不应该在结果中.
我在以下版本上测试了它,总是得到相同的结果:
> Oracle Database 11g企业版11.2.0.3.0版 – 64位生产
> Oracle Database 12c企业版12.1.0.2.0版 – 64位生产
解决方法
不,这不是一个错误.聚合函数是您看到此意外结果的原因.下面是它的工作原理.如果查询没有返回任何行,则SUM()函数以及MAX()函数将返回NULL(产生1行).当您执行查询时,优化器应用谓词推送转换,并且您的原始查询将变为(不会发布整个跟踪,仅发布已转换的查询):
SELECT "from$_subquery$_001"."C1" "C1","from$_subquery$_001"."C2" "C2" FROM ( (SELECT 'ASDF' "C1",MAX(SUM(1)) "C2" FROM "SYS"."DUAL" "DUAL" WHERE 'ASDF'<>'ASDF' [1]-- predicate pushed into the view GROUP BY "DUAL"."DUMMY" ) UNION (SELECT 'JKLÖ' "C1",1 "C2" FROM "SYS"."DUAL" "DUAL" WHERE 'JKLÖ'<>'ASDF')) "from$_subquery$_001"
[1]由于谓词推送你的第一个子查询没有返回任何行,当一个聚合函数(除了count和其他几个),MAX或SUM或者甚至两者都在这个情况下用于空结果集NULL时将返回 – 1行第二个子查询返回1行,从而生成您正在查看的2行结果集.
这是一个简单的演示:
create table empty_table (c1 varchar2(1)); select 'aa' literal,nvl(max(c1),'NULL') as res from empty_table LIteraL RES ------- ---- aa NULL 1 row selected.