2010-01-29 105 views
5

可以以某種方式連接表並避免在以下MySQL查詢中使用distinct。 invited_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 *一次*邀請。 – 2010-01-29 08:49:59

+0

@Lieven由於表格被連接兩次,所以你可以得到重複的行。 – 2010-01-29 17:22:25

回答

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上。 – 2010-01-29 20:19:03

+0

好點,不知道爲什麼我在那裏輸入錯誤的東西。 – glenatron 2010-02-01 14:45:29

+0

嗯......現在更有意義了! :) – 2010-02-01 16:31:24

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(sum(user2.signup_date >= NOW() - INTERVAL 30 DAY), 0)