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 列中。子查询计算有多少参赛者推荐了其他用户。我目前正在尝试找到另一种在没有子查询的情况下编写它的方法,因为查询本身需要很长时间才能运行。如果有人有任何建议或建议,请分享!

4

1 回答 1

1

这应该返回一个等效的结果。这里的区别在于,我们有一个内联视图(MySQL 将其称为派生表),而不是相关子查询,它的别名为rf.

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())。

于 2012-12-19T03:14:53.633 回答