2010-01-29 8 views
5

Могу ли я каким-то образом присоединиться к таблицам и избежать использования отдельных в следующем запросе MySQL. invite_by_id показывает идентификатор пользователя, который пригласил этого пользователя.Как оптимизировать вложенный запрос?

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

Зачем вам нужен отдельный? Мне кажется, что пользователю X разрешено приглашать только пользователем Y * one * time. –

+0

@Lieven Поскольку таблица соединяется дважды, вы можете получить повторяющиеся строки. –

ответ

1

попробовать что-то например, я изменил имена таблиц подзапроса, чтобы сделать его более понятным:

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 

Если это что-то вы бежите часто, убедитесь, что user.invited_by_id проиндексирован!

1

Если вы используете версию MySQL больше, чем 5.0.37 у вас есть Profiler доступны, которые могли бы дать вам довольно хорошее представление о том, где находятся узкие места на любой запрос. Это может быть хорошей отправной точкой - возможно, вы можете отредактировать вывод в исходном вопросе, если не знаете, как лучше его интерпретировать.

+0

Он на mysql. –

+0

Хорошая мысль, не знаю, почему я набрал неправильную вещь. – glenatron

+0

А ... Это сейчас намного больше смысла! :) –

3

Я предполагаю, что вы пытаетесь подсчитать количество раз, когда пользователь был приглашен, и количество раз, сколько раз этот пользователь был приглашен за последние 30 дней.

В этом случае вы можете сделать запрос с помощью простой условной суммы, как:

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 

Если обнуляет в theCount2 будет проблемой, использовать COALESCE как:

coalesce(sum(user2.signup_date >= NOW() - INTERVAL 30 DAY), 0) 
Смежные вопросы