Процент, основанный на иностранном ключе - PullRequest
0 голосов
/ 08 января 2019

У меня есть таблица с именем animals, в которой есть следующие столбцы:

id: INT
state: VARCHAR

И еще одна таблица, называемая домами со следующими столбцами:

id: INT
animal_id: INT
color: VARCHAR

Я пытаюсь получить процент животных (это состояние «живое») и их идентификаторы находятся в заданном наборе, у которого есть хотя бы дом (цвет которого «красный»). Если у одного животного более одного красного дома, это не имеет значения, его нужно просто посчитать один раз.

Я знаю, как определить количество животных с такими условиями:

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

И я знаю, как получить дома с такими условиями:

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

Я не совсем уверен, как объединить оба запроса, чтобы получить процент животных.

Пример данных:

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'  

И мы хотим отнести животных к животным с идентификаторами 1, 2, 3 и 5.

Итак, поскольку животные с идентификаторами 2 и 5 мертвы, их не следует считать частью знаменателя. Теперь это оставляет нас с животными 1 и 3, но просто животное с идентификатором 1 имеет по крайней мере один красный дом (обратите внимание, что у него есть два, но нам все равно), что означает, что процент :

(1 животное по крайней мере с одним читающим домом) / (2 живых животных) = 50%

Ответы [ 3 ]

0 голосов
/ 08 января 2019

Выберите animal_id, цвет, живущий из дома t1 Внутреннее соединение (выберите Id, считайте (*) как живущих из группы животных по id) t2 На t1.animalid = t2.id, где color = 'red'

0 голосов
/ 08 января 2019

Оператор EXISTS позволяет вам проверить, есть ли у животного хотя бы один красный дом, не беспокоясь о дублировании результатов в JOIN. Использование его в качестве условия CASE WHEN в функции группировки AVG должно вернуть ожидаемые результаты.

Вот (непроверенный) запрос

SELECT AVG(CASE WHEN exists(SELECT id
                            FROM houses
                            WHERE color = 'red' and animal_id = a.id
                            LIMIT 1) 
                THEN 100.0 ELSE 0.0 END)
FROM animals a
WHERE a.state = 'living' 
AND a.id IN (10,11,12)
0 голосов
/ 08 января 2019

Вы можете использовать LEFT JOIN для объединения таблиц. Затем AVG() можно использовать для получения желаемого соотношения:

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);

Для пересмотренного расчета вы можете использовать:

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);
...