Se la query coinvolge grandi parti di b
e/o c
è più efficiente aggregare prima e unire successivamente.
Mi aspetto che queste due varianti siano notevolmente più veloci:
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);
Devi tenere conto della possibilità che alcuni a_id
non sono affatto presenti in a
e/o b
. count()
non restituisce mai NULL
, ma questo è un freddo conforto di fronte a LEFT JOIN
, che ti lascia con NULL
comunque i valori per le righe mancanti. devi prepararsi per NULL
. Usa COALESCE()
.
Oppure UNION ALL a_id
da entrambe le tabelle, aggrega, poi ISCRIVITI:
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);
Probabilmente più lento. Ma ancora più veloce delle soluzioni presentate finora. E potresti fare a meno di COALESCE()
e ancora non perdere nessuna riga. Potresti ottenere occasionalmente NULL
valori per bc_ct
, in questo caso.