2012-12-19 134 views
0

所以我正在優化一個SQL查詢的過程。我已經清理了它,但仍有一些工作要做。請參見下面的查詢:不使用子查詢重寫查詢

競賽TBL: ID,fb_share_points,tw_share_points

comp_mapper TBL: ID,referrer_user_id,user_subscription_id,has_fb_shared,has_tw_shared,competition_id

SELECT 
    IF (cm.has_fb_shared = 1, IFNULL(c.fb_share_points,0), 0) 
    + IF (cm.has_tw_shared = 1, IFNULL(c.tw_share_points,0), 0) 
    + (SELECT count(*) FROM comp_mapper as cm2 
     WHERE cm2.comp_id = cm.comp_id 
     AND cm2.referrer_user_id = us.user_id) 
    as shares 
FROM competitions AS c 
JOIN comp_mapper as cm ON cm.competition_id = c.id 
JOIN user_subscription as us on cm.user_subscription_id = us.id 
WHERE c.id = :id 
ORDER BY shares DESC 
LIMIT :limit 

當用戶被稱爲,在引用用戶的ID被放入競爭參賽者的referrer_user_id列中。子查詢計算有多少競爭者參與其他用戶。我目前正試圖找到另一種不帶子查詢的方式,因爲查詢本身需要很長時間才能運行。如果有人有任何建議或建議,那麼請分享!

回答

1

這應該返回一個等效的結果。這裏的區別是,而不是相關的子查詢,我們有一個內聯視圖(MySQL稱之爲派生表),其別名爲​​。

SELECT IF(cm.has_fb_shared = 1, IFNULL(c.fb_share_points,0), 0) 
    + IF(cm.has_tw_shared = 1, IFNULL(c.tw_share_points,0), 0) 
    + IFNULL(rf.ref_count,0) AS shares 
    FROM competitions c 
    JOIN comp_mapper cm 
    ON cm.competition_id = c.id 
    JOIN user_subscription us 
    ON us.id = cm.user_subscription_id 
    LEFT 
    JOIN ( 
     SELECT cm2.referrer_user_id 
       , COUNT(1) AS ref_count 
      FROM comp_mapper cm2 
      WHERE cm2.comp_id = :id 
      GROUP BY cm2.referrer_user_id 
     ) rf 
    ON rf.referrer_user_id = us.user_id 
WHERE c.id = :id 
ORDER BY shares DESC 
LIMIT :limit 

這令我有些奇怪的是,查詢返回一組行只有一個單一的列(shares),並沒有其他的列。如果意圖要返回單個值,則需要在選擇列表中具有聚合函數(即SUM())。

+0

優秀的回覆,非常感謝!有更多的專欄,我排除他們保持關鍵。 – Rijndael