Percentage based on foreign_key

Viewed 45

I have a table called animals that have the following columns:

id: INT
state: VARCHAR

And another table called houses that have the following columns:

id: INT
animal_id: INT
color: VARCHAR

I am trying to get the percentage of animals (which state is 'living') and its ids are within a given set, that have at least a house (which color is 'red'). If one animal has more than one red house, it doesn't matter, it should just be counted once.

I know how to get the number of animals with those conditions:

SELECT COUNT(*)
FROM animals
WHERE state = 'living'
AND id IN (10,11,12)

And I know how to get the houses with those conditions:

SELECT COUNT(*)
FROM houses
WHERE color = 'red'

I am not exactly sure how to combine both queries to get a percentage of animals.

Sample data:

animals (id, state)

1, 'living'
2, 'dead'
3, 'living'
4, 'living'
5, 'dead'
6, 'living'


houses (id, animal_id, color)

1, 1, 'red'
2, 2, 'red'
3, 1, 'blue'
4, 6, 'red'
5, 4, 'red'
6, 1, 'red'  

And we want to scope down the animals to just the ones with ids 1, 2, 3 and 5.

So, since the animals with ids 2 and 5 are dead, they should not be counted as part of the denominator. Now, this leaves us with animals 1 and 3, but just animal with id 1 has at least one red house (notice that it has two, but we don't care), which means that the percentage is:

(1 animal with at least one read house) / (2 animals that are living) = 50%

2 Answers

You can use a LEFT JOIN to combine the tables. Then AVG() can be used to get the ratio you want:

SELECT AVG( (h.color = 'red')::int ) as ratio_red
FROM animals a LEFT JOIN
     houses h
     ON a.id = h.animal_id
WHERE a.state = 'living'
      a.id IN (10, 11, 12);

For the revised calculation, you can use:

SELECT COUNT(DISTINCT CASE WHEN h.color = 'red' THEN h.animal_id END) / COUNT(DISTINCT a.id) as ratio_red
FROM animals a LEFT JOIN
     houses h
     ON a.id = h.animal_id
WHERE a.state = 'living'
      a.id IN (10, 11, 12);

Select animal_id,color ,living from house t1 Inner join(select Id,count(*) as living from animal group by id) t2 On t1.animalid=t2.id where color='red'

Related