Om frågan omfattar stora delar av b
och/eller c
det är mer effektivt att aggregera först och gå med senare.
Jag förväntar mig att dessa två varianter är betydligt snabbare:
SELECT a.id,
,COALESCE(b.ct, 0) + COALESCE(c.ct, 0) AS bc_ct
FROM a
LEFT JOIN (SELECT a_id, count(*) AS ct FROM b GROUP BY 1) b USING (a_id)
LEFT JOIN (SELECT a_id, count(*) AS ct FROM c GROUP BY 1) c USING (a_id);
Du måste ta hänsyn till möjligheten att vissa a_id
finns inte alls i a
och/eller b
. count()
returnerar aldrig NULL
, men det är kall komfort inför LEFT JOIN
, vilket ger dig NULL
värden för saknade rader ändå. Du måste förbered dig för NULL
. Använd COALESCE()
.
Eller UNION ALL a_id
från båda tabellerna, samla, sedan GÅ MED:
SELECT a.id
,COALESCE(ct.bc_ct, 0) AS bc_ct
FROM a
LEFT JOIN (
SELECT a_id, count(*) AS bc_ct
FROM (
SELECT a_id FROM b
UNION ALL
SELECT a_id FROM c
) bc
GROUP BY 1
) ct USING (a_id);
Förmodligen långsammare. Men fortfarande snabbare än de lösningar som presenterats hittills. Och du skulle klara dig utan COALESCE()
och fortfarande inte tappar några rader. Du kan ibland få NULL
värden för bc_ct
, i det här fallet.