2010-01-29 25 views
5

¿De qué manera puedo unir mesas y evitar el uso de distinct en la siguiente consulta MySQL? invited_by_id muestra la identificación de usuario de quién invitó a este usuario.¿Cómo optimizar una consulta anidada?

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; 
+0

¿Por qué necesitarías distinguir? Me parece que al usuario X solo se le debe permitir que sea invitado por el usuario Y * one * time. –

+0

@Lieven Dado que la tabla se está uniendo dos veces, puede obtener filas duplicadas. –

Respuesta

1

probar algo así, cambié los nombres de la tabla de subconsulta para que sea un poco más clara:

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 

Si esto es algo ¡se ejecuta a menudo, asegúrese de que user.invited_by_id esté indexado!

1

Si está ejecutando una versión de MySQL 5.0.37 mayor que ustedes tienen un Profiler disponibles para usted que podría darle una muy buena idea de dónde están los cuellos de botella en cualquier consulta. Ese podría ser un buen punto de partida; podría editar el resultado en la pregunta original si no está seguro de cuál es la mejor manera de interpretarlo.

+0

Él está en mysql. –

+0

Buen punto, no tengo idea de por qué escribí algo incorrecto allí. – glenatron

+0

Ah ... ¡Eso tiene mucho más sentido ahora! :) –

3

Supongo que está tratando de contar cuántas veces ha sido invitado un usuario y cuántas veces ha sido invitado en los últimos 30 días.

En este caso se podría hacer la consulta con una simple suma condicional:

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 

Si los nulos en theCount2 será un problema, use un fusionan como:

coalesce(sum(user2.signup_date >= NOW() - INTERVAL 30 DAY), 0) 
Cuestiones relacionadas