В этом случае коррелированные подзапросы могут быть простейшим решением:
select m.*,
(select count(*) from trans1 t where t.user_id = m.user_id) as cnt1,
(select count(*) from trans2 t where t.user_id = m.user_id) as cnt2,
(select count(*) from trans3 t where t.user_id = m.user_id) as cnt3
from master m;
С индексом user_id
в каждой из транс-таблиц производительность также должна быть очень хорошей.
Более каноническое решение будет использовать left join
и несколько group by
s:
select m.user_id,
coalesce(t1.cnt, 0) as cnt1,
coalesce(t2.cnt, 0) as cnt2,
coalesce(t3.cnt, 0) as cnt3
from master m left join
(select t.user_id, count(*) as cnt
from trans1 t
group by t.user_id
) t1
on t1.user_id = m.user_id left join
(select t.user_id, count(*) as cnt
from trans2 t
group by t.user_id
) t2
on t2.user_id = m.user_id left join
(select t.user_id, count(*) as cnt
from trans3 t
group by t.user_id
) t3
on t3.user_id = m.user_id;
Первая версия проще в написании и в большинстве случаев может даже иметь лучшую производительность.