Я бы подошел к этому, используя union all
и агрегацию. Это начинается с получения информации о флаге для пользователя:
select user_id, max(is_mobile) as is_mobile, max(is_web_as is_web)
from ((select distinct user_id, 1 as is_mobile, 0 as is_web
from mobile
) union all
(select distinct user_id, 0, 1
from web
)
) u
group by user_id;
Затем объедините это далее:
select sum(is_mobile) as num_mobile,
sum(is_web) as num_web,
sum(is_mobile * is_web) as num_mobile_and_web,
avg(is_mobile * (1 - is_web)) as mobile_only_rate,
avg(is_web * (1 - is_mobile)) as web_only_rate,
avg(is_mobile * is_web) as mobile_and_web_rate
from (select user_id, max(is_mobile) as is_mobile, max(is_web_as is_web)
from ((select distinct user_id, 1 as is_mobile, 0 as is_web
from mobile
) union all
(select distinct user_id, 0, 1
from web
)
) u
group by user_id
) u;