W powyższym zapytaniu doświadczasz zagregowanego fanoutu.
Dzieje się tak, ponieważ istnieje
- sprzężenie 1-1 lub 1-N między
aaa
&bbb
- istnieje złącze 1-N między
bbb
&ccc
To ostatnie połączenie tworzy M
duplikaty dla wierszy istniejących w bbb
jeśli są połączone z wierszami M za pomocą sprzężenia z ccc
Aby naprawić błąd, podziel zapytanie na dwa CTE i dołącz do wyniku.
WITH agg_bb AS (
SELECT aa.id, sum(bb.count)
FROM aaaa aa
LEFT JOIN bbbb bb ON bb.aa_id = aa.id
GROUP BY aa.id
)
, agg_cc AS (SELECT aa.id, count(DISTINCT cc.id)
FROM aaaa aa
LEFT JOIN bbbb bb ON bb.aa_id = aa.id
LEFT JOIN cccc cc ON cc.bb_id = bb.id
GROUP BY aa.id
)
SELECT * FROM agg_bb JOIN agg_cc USING (id)
Ogólnie, aby uniknąć rozgałęzień, stosuj tylko operacje agregujące na kolumnach z relacji znajdującej się najbardziej po prawej stronie w serii złączeń. Jeśli zauważysz, że agregujesz kolumny ze środkowych tabel, podziel zapytanie tak, jak to zrobiłem powyżej. Tylko następujące funkcje są niezmienne w rozproszeniu:COUNT DISTINCT
, MIN
, MAX