使用时返回的行数与这些行的数量之间的差异

时间:2012-03-01 11:08:37

标签: sql oracle

在使用having子句时,似乎count(*)之前会计算having,但会在之后评估返回的行数。修复可能是子查询,但如果可以避免它,我想。我正在使用count(*)来避免no_data_found

此行为发生在11.2.0.1.0,10.2.0.1.0,9.2.0.7.0中,所以它显然是有意的,但我不太明白为什么。下面是一个易于复制的例子。

有谁知道为什么会这样?我希望count(*)能够返回1

create table tmp_test1 as
  select level as id, level as val
    from dual
 connect by level <= 1000
         ;

Table created.

create table tmp_test2 as
  select level as id, level as val
    from dual
 connect by level <= 1000
         ;

Table created.

select count(*) as count
  from tmp_test1 a
  join tmp_test2 b
    on a.id = b.id
having max(a.val) = max(b.val)
       ;

     COUNT
----------
      1000

select 1 as num_rows
  from tmp_test1 a
  join tmp_test2 b
    on a.id = b.id
having max(a.val) = max(b.val)
       ;

  NUM_ROWS
----------
         1

3 个答案:

答案 0 :(得分:3)

来自documentation

  

当不使用GROUP BY时,HAVING的行为类似于WHERE子句。

所以,它可能是这样的:

select count(*) as count
  from tmp_test1 a
  join tmp_test2 b
    on a.id = b.id

这部分将为您提供count

的1000
having max(a.val) = max(b.val)

只能获得一条记录。


在这种情况下,因为它也会为你提供一条记录。

select 1 as num_rows
  from tmp_test1 a
  join tmp_test2 b
    on a.id = b.id
having max(a.val) = max(b.val)
       ;

答案 1 :(得分:3)

having子句在组级别运行 - 没有指定group by,这意味着它在整个数据集中运行。

这意味着在任何带有having子句且没有group by子句的查询中,结果只能返回0行(如果having条件为假)或1行(如果having条件为真。)

答案 2 :(得分:1)

你认为这是错的......

select count(*) as count
  from tmp_test1 a
  join tmp_test2 b
    on a.id = b.id

此部分只返回一行,值为1000

having max(a.val) = max(b.val)

并且这部分将应用可能被认为是您之前得到的where条件(因此它将仅被评估一次),并且作为max(a)= max(b),它将返回true。