Разница между количеством возвращаемых строк и количеством этих строк при использовании - PullRequest
3 голосов
/ 01 марта 2012

Похоже, что при использовании предложения 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 ]

3 голосов
/ 01 марта 2012

Предложение having работает на уровне группы. Если группа не указана, это означает, что оно работает по всему набору данных.

Это означает, что в любом запросе с предложением havingи без условия group by результаты могут возвращать только 0 строк (если условие having ложно) или 1 строку (если условие having истинно).

3 голосов
/ 01 марта 2012

Из документации :

Когда GROUP BY не используется, HAVING ведет себя как предложение WHERE.

Итак, это может быть что-токак это:

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

Эта часть даст вам 1000 для count, а

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 голос
/ 01 марта 2012

Вы думаете, что это неправильно ...

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)

и эта часть будет применять то, что можно представить как условие для того, что вы ранее получили (поэтому оно будет оцениваться только один раз), и как max (a) = max (b) возвращает true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...