Como otimizar uma consulta aninhada?
-
23-09-2019 - |
Pergunta
De alguma forma, posso me juntar às tabelas e evitar o uso de distintos na seguinte consulta MySQL. Invido_by_id mostra o ID do usuário de quem convidou esse usuário.
SELECT
user1.id, count(distinct user2.id) AS theCount, count(distinct user3.id) AS theCount2
FROM
users AS user1
LEFT OUTER JOIN
users AS user2 ON user2.invited_by_id=user1.id
LEFT OUTER JOIN (
SELECT id, invited_by_id FROM users WHERE signup_date >= NOW() - INTERVAL 30 DAY
) AS user3 ON user3.invited_by_id=user1.id
GROUP BY user1.id;
Solução
Experimente algo assim, mudei os nomes de tabela da sub-quadra para deixar um pouco mais claro:
Select
user.id,
all_time.total AS theCount,
last_month.total AS theCount2
From users AS user
Left Outer Join
(Select Count(id) as total, invited_by_id
From users
Group By invited_by_id) as all_time
On all_time.invited_by_id = user.id
Left Outer Join
(Select Count(id) as total, invited_by_id
From users
Where signup_date >= NOW() - INTERVAL 30 DAY
Group By invited_by_id) AS last_month
On last_month.invited_by_id = user.id
Se isso é algo que você corre com frequência, verifique se isso user.invited_by_id
é indexado!
Outras dicas
Estou assumindo aqui que você está tentando contar quantas vezes um usuário foi convidado e uma contagem de quantas vezes esse usuário foi convidado nos últimos 30 dias.
Nesse caso, você pode fazer a consulta com uma soma condicional simples como:
select user1.id, count(user2.id) as tehCount, sum(user2.signup_date >= NOW() - INTERVAL 30 DAY) as theCount2
from users as user1
left outer join users as user2 on user2.invited_by_id = user1.id
group by user1.id
Se os nulos no país 2 serão um problema, use uma coalesce como:
coalesce(sum(user2.signup_date >= NOW() - INTERVAL 30 DAY), 0)
Se você está executando uma versão do MySQL maior que 5.0.37, você tem um analisador Disponível para você que possa lhe dar uma boa idéia de onde estão os gargalos em qualquer consulta. Esse pode ser um bom ponto de partida- talvez você possa editar a saída na pergunta original, se você não tiver certeza sobre a melhor forma de interpretá-la.