Что не так, так это то, что вы создаете декартово произведение между score
и card
.
Вот как это работает: когда вы присоединяете deck
к score
, у вас может совпадать несколько строк. Затем каждая из этих нескольких строк соединяется с всеми соответствующих строк в card
. Нет условий, препятствующих этому, и поведение соединения по умолчанию, когда никакие условия не ограничивают его, состоит в объединении всех строк в одной таблице со всеми строками в другой таблице.
Чтобы увидеть его в действии, попробуйте этот запрос без группы:
select *
from deck
left outer join score on deck.id=score.deckId
left outer join card on deck.id=card.deckId;
Вы увидите много повторяющихся данных в столбцах, которые взяты из score
и card
. Когда вы вычисляете AVG()
для данных, в которых есть повторы, избыточные значения магически исчезают (до тех пор, пока значения повторяются равномерно). Но когда вы COUNT()
или SUM()
их, итоговые суммы далеко.
Могут быть средства от непреднамеренных декартовых продуктов. В вашем случае вы можете использовать COUNT(DISTINCT)
для компенсации:
select deck.name, avg(score.value) "Ave", count(DISTINCT card.front) "Count"
from deck
left outer join score on deck.id=score.deckId
left outer join card on deck.id=card.deckId
group by deck.id;
Это решение не решает все случаи непреднамеренных декартовых продуктов. Более универсальное решение состоит в том, чтобы разбить его на два отдельных запроса:
select deck.name, avg(score.value) "Ave"
from deck
left outer join score on deck.id=score.deckId
group by deck.id;
select deck.name, count(card.front) "Count"
from deck
left outer join card on deck.id=card.deckId
group by deck.id;
Не все задачи в программировании баз данных должны выполняться в одном запросе. Может быть даже более эффективным (а также более простым, простым в модификации и менее подверженным ошибкам) для использования отдельных запросов, когда вам требуется несколько статистических данных.