Home > Software engineering >  Calculate ratio between 2 rows in PSQL
Calculate ratio between 2 rows in PSQL

Time:04-08

I have a table like

groupid numofproducts matches
1 5 false
1 1 true
2 1 true
2 1 false

and need to calculate a simple ratio along the lines of

for a group, calculate the ratio of matches to the total set of products

so for group 1 the ratio would be 1/6, or 16.67%, group 2 would be 1/2 or 50%

CodePudding user response:

You can use conditional aggregation to get the result you want. For example

select
  groupid,
  1.0 * sum(case when matches then numofproducts else 0 end) /
  sum(numofproducts) as ratio 
from t
group by groupid
order by groupid

Result:

 groupid  ratio                  
 -------- ---------------------- 
 1        0.16666666666666666667 
 2        0.50000000000000000000 

See running example at DB Fiddle.

CodePudding user response:

You can use the FILTER clause of count function clause to count only those where matches is true and use sum sunction to get the total num_of_products. From there is just a simple math operation. So:

with test (groupid, numofproducts,  matches) as
     (values (1, 5, false)
           , (1, 1, true)
           , (2, 1, true)
           , (2, 1, false)
     )
-- your query starts here
select groupid, round( ( 100.0*count(*) filter (where matches)/sum(numofproducts)),2)  pct_matches
  from test
 group by groupid;

CodePudding user response:

You can do it with conditional aggregation with SUM() aggregate function if you use a FILTER clause:

SELECT groupid,
       ROUND(100.0 * SUM(numofproducts) FILTER (WHERE matches) / SUM(numofproducts), 2) ratio
FROM tablename
GROUP BY groupid
ORDER BY groupid;

I assume that the data type of the column matches is BOOLEAN.
If it is VARCHAR then change the WHERE clause to: WHERE matches = 'true'.

If there is a case that there are not any true values in the column matches for a groupid then you should also use COALESCE() to get 0 instead of null as result:

SELECT groupid,
       ROUND(100.0 * COALESCE(SUM(numofproducts) FILTER (WHERE matches), 0) / SUM(numofproducts), 2) ratio
FROM tablename
GROUP BY groupid
ORDER BY groupid; 

See the demo.

  • Related