Summary: it doesn't make any difference, and it has never had it in Oracle, at least since version 6 (1989), when I first started hearing about smart ways of counting faster by selecting primary key columns, etc., like if Oracle were unaware that people sometimes think of something.
You can see what the parser / optimizer does with the expression, using it in the filter and checking the Predicates section of the execution plan.
create table demo ( demo_id integer generated always as identity constraint demo_pk primary key , othercolumn integer ); insert into demo (othercolumn) select dbms_random.value(0,1000) from dual connect by rownum <= 10000; commit; call dbms_stats.gather_table_stats(user, 'demo');
Normal count(*) (Oracle 12.1):
select count(*) from demo having count(*) > 1 Plan hash value: 1044424301 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 (0)| 00:00:01 | |* 1 | FILTER | | | | | | 2 | SORT AGGREGATE | | 1 | | | | 3 | INDEX FAST FULL SCAN| DEMO_PK | 10000 | 7 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(COUNT(*)>1)
Clever superfast expression:
select sum(case when 1=1 then 1 else 0 end) from demo having sum(case when 1=1 then 1 else 0 end) > 0 Plan hash value: 1044424301 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 (0)| 00:00:01 | |* 1 | FILTER | | | | | | 2 | SORT AGGREGATE | | 1 | | | | 3 | INDEX FAST FULL SCAN| DEMO_PK | 10000 | 7 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(SUM(1)>0)
Notice the Predicates section, which shows that the sum expression has been evaluated and replaced with sum(1) . (I donβt have time to dig into tracefiles right now, but Iβm sure they will show that the rewriting happened before CBO optimization.)
Here, what he does with count(1) , another expression is sometimes considered more efficient than the standard one:
select count(1) from demo having count(1) > 1 Plan hash value: 1044424301 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 (0)| 00:00:01 | |* 1 | FILTER | | | | | | 2 | SORT AGGREGATE | | 1 | | | | 3 | INDEX FAST FULL SCAN| DEMO_PK | 10000 | 7 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(COUNT(*)>1)
And here is a plan without filters:
select sum(case when 1=1 then 1 else 0 end) as rowcount from demo Plan hash value: 2242940774 ------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| DEMO_PK | 10000 | 7 (0)| 00:00:01 | -------------------------------------------------------------------------
As you can see, they are all the same (except for differences in the state of the artificial filter).
In addition, sum(1) does not give the same results as count(*) when there are no lines:
select sum(case when 1=1 then 1 else 0 end) as sum1 , count(*) from demo where 1=2 SUM1 COUNT(*)