Search notes:

Oracle SQL: HAVING clause

The having clause allows to formulate rules which specify which aggregated rows are returned.
With 21c, macros for scalar expressions can be used inside the having clause.

Order of GROUP BY and HAVING clause

When combining group by with having, the order in which these clauses appear is unimportant. Both of the following two queries are equivalent:
select
   sum(num)  sum_num,
   txt
from
   tq84_tab
group by
   txt
having
   sum(num) > 0;


select
   sum(num)  sum_num,
   txt
from
   tq84_tab
having
   sum(num) > 0
group by
   txt;

Bug ?

create table tq84_h (a number, b varchar2(10));
 
begin
   rollback;
   insert into tq84_h values (1, 'one'  );
-- insert into tq84_h values (3, 'three');
   insert into tq84_h values (1, 'ONE'  );
   insert into tq84_h values (2, 'two'  );
end;
/
 
-- explain plan for
select /*+ no_push_pred */ * from (
   select case when max(count(*))  > 1 then 'a is not unique' end t from tq84_h group by a having count(*) > 1  union all
   select case when max(length(b)) > 5 then 'b has values longer  than 5 characters' end t from tq84_h
)
where t is not null;
 
 
select               count(*)                                    from tq84_h group by a;
select               count(*)                                    from tq84_h group by a having count(*) > 1;
select               count(*)                                    from tq84_h group by a having count(*) > 2;
select           max(count(*))                                   from tq84_h group by a;
select           max(count(*))                                   from tq84_h group by a having count(*) > 2;
select case when max(count(*))  > 1 then 'a is not unique' end t from tq84_h group by a having count(*) > 1;
select case when max(count(*))  > 2 then 'xyz'             end t from tq84_h group by a having count(*) > 2;
 
select * from (
select case when max(count(*))  > 2 then 'xyz'             end t from tq84_h group by a having count(*) > 2
)
where t is  not null;
 
select * from (
select case when max(count(*))  > 2 then 'xyz'             end t from tq84_h group by a having count(*) > 2
union all select 'mmm' t from dual
)
where t is  not null;
 
create view tq84_v as
select case when max(count(*))  > 2 then 'xyz'             end t from tq84_h group by a having count(*) > 2
union all select 'mmm' t from dual;
 
select * from tq84_v where t is not null;

explain plan for
select * from tq84_v where t is not null;

select * from dbms_xplan.display();

drop   table tq84_h;

See also

In order for a materialized view to be fast refreshable, the query must not have a having clause.

Index

Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 8 attempt to write a readonly database in /home/httpd/vhosts/renenyffenegger.ch/php/web-request-database.php:78 Stack trace: #0 /home/httpd/vhosts/renenyffenegger.ch/php/web-request-database.php(78): PDOStatement->execute(Array) #1 /home/httpd/vhosts/renenyffenegger.ch/php/web-request-database.php(30): insert_webrequest_('/notes/developm...', 1740464801, '18.219.27.69', 'Mozilla/5.0 App...', NULL) #2 /home/httpd/vhosts/renenyffenegger.ch/httpsdocs/notes/development/databases/Oracle/SQL/select/aggregate/having/index(117): insert_webrequest() #3 {main} thrown in /home/httpd/vhosts/renenyffenegger.ch/php/web-request-database.php on line 78