Home > Net >  How to count records by ID and then print only record with id count above average?
How to count records by ID and then print only record with id count above average?

Time:11-26

exp1 and exp2 Select * exp 1 gives me:

ID exp_2_ID Name
1 1 a
2 1 b
3 2 c

Select * exp 2 gives me:

ID name
1 print
2 no_print

Now what I want to do is count every id and then print only when number of id's are above average

So in math way it should be something like this exp_2_id 1 = count 2 exp_2_id 2 = count 1 average = 3/2 = 1.5 Should print only exp_2 id 1 cause it is 2

Hope that someone can explain me how to do it

So as an output I want to have only

ID name
1 print

CodePudding user response:

This is how I understood it; read comments within code.

Sample data:

SQL> with
  2  exp1 (id, exp_2_id, name) as
  3    (select 1, 1, 'a' from dual union all
  4     select 2, 1, 'b' from dual union all
  5     select 3, 2, 'c' from dual
  6    ),
  7  exp2 (id, name) as
  8    (select 1, 'print'    from dual union all
  9     select 2, 'no_print' from dual
 10    ),

Query begins here:

 11  temp as
 12    -- number of rows in each of these tables
 13    (select (select count(*) from exp1) cnt_1,
 14            (select count(*) from exp2) cnt_2
 15     from dual
 16    ),
 17  temp2 as
 18    -- number of rows per each EXP_2_ID in EXP1 table
 19    (select a.exp_2_id,
 20            count(*) cnt_id
 21     from exp1 a
 22     group by a.exp_2_id
 23    )
 24  -- Finally, select EXP2 row(s) whose number (per ID) is larger than the average
 25  select b.id, b.name
 26  from exp2 b join temp2 t2 on t2.exp_2_id = b.id
 27  where t2.cnt_id > (select t.cnt_1 / t.cnt_2 from temp t);

        ID NAME
---------- --------
         1 print

SQL>

CodePudding user response:

An option would be using Count Analytic Function such as

WITH e AS 
(
  SELECT DISTINCT
         e2.ID , 
         e2.Name,
         COUNT(*) OVER () / COUNT(*) OVER (PARTITION BY e2.ID) AS ratio,
         COUNT(DISTINCT e2.ID) OVER () AS total   
    FROM exp2 e2
    JOIN exp1 e1
      ON e1.exp_2_ID = e2.ID
)
SELECT ID, Name
  FROM e
 WHERE total > ratio

Demo

CodePudding user response:

You want to look at table exp1 and count rows per exp_2_id. Then you want to keep those exp_2_id the count of which is above average. At last you want to select all rows of table exp2 that match those IDs.

You can use AVG(COUNT(*)) OVER () to get the average of the counts.

One way to write the query:

select *
from exp2
where (id, 'ABOVE AVERAGE') in
(
  select 
    exp_2_id,
    case when count(*) > avg(count(*)) over () 
      then 'ABOVE AVERAGE' 
      else 'NOT ABOVE AVERAGE'
    end
  from exp1
  group by exp_2_id 
);

If this looks a bit clumsy, it is because window functions are applied last in a query, so we cannot use WHERE directly to get the rows above average. Some DBMS feature a QUALIFY clause that does that, but Oracle does not have such a clause.

  • Related