0

我有这个查询要执行:

SELECT u1.firstname,
       u1.lastname,
       u1.totalcommission,
       u1.userid,
       count(DISTINCT u2.userid) AS level1,
       count(DISTINCT u3.userid) AS level2
FROM users AS u1
INNER JOIN users AS u2 ON u1.userid = u2.affiliate1
AND u2.signupdate BETWEEN '2011-01-01 00:00:00' AND '2013-04-02 23:59:59'
LEFT JOIN users AS u3 ON u1.userid = u3.affiliate2
WHERE u1.usertypeid != '1'
GROUP BY u1.userid
ORDER BY count(DISTINCT u2.userid) DESC

表的索引:

PRIMARY BTREE   Yes No  userid  41318   A   No  
email   BTREE   Yes No  email   41318   A   No  
affiliate1  BTREE   No  No  affiliate1  1967    A   Yes 
affiliate2  BTREE   No  No  affiliate2  258 A   Yes 
signupdate  BTREE   No  No  signupdate  41318   A   No

查询有效,但问题是速度非常慢(表 users 有 43k 行,仅此而已),由于 count(distinct) 函数,它需要大约 10 秒。有没有办法用性能更好的东西代替它?

谢谢,

/卢卡

4

2 回答 2

0

您已经按 user_id 分组,而不是按订单计数。或者,您可以使用 DESC 和 group by 简单地订购它

SELECT
  u1.firstname,
  u1.lastname,
  u1.totalcommission,
  u1.userid,
  count( distinct u2.userid ) AS level1,
  count( distinct u3.userid ) AS level2
FROM users AS u1
  INNER JOIN users AS u2
    ON u1.userid = u2.affiliate1
  INNER JOIN users AS u3
    ON u1.userid = u3.affiliate2
WHERE u1.usertypeid != '1'
    and u2.signupdate between '2011-01-01 00:00:00'
    and '2013-04-02 23:59:59'
GROUP BY u1.userid DESC , u2.userid , u3.userid
于 2013-04-02T09:08:43.727 回答
0

由于一些意想不到的笛卡尔结果,您可能会受到重创。我会尝试以下。由于您的第一个内部联接基于必须存在的affiliate1 条目,因此我将预先汇总这些条目以获得每个附属公司的 1 条记录,其中附属公司的 ID 加入回用户表,并且仅获取用户类型为 != '1' 的那些。这基本上为您创建了您的计数 DISTINCT。然后,加入用户表以获取此会员的用户信息。然后,做一个类似的左连接,但是对于第二个会员(如果有的话......也基于会员的用户类型!='1')。

现在,您将在 MAX 中获得每张桌子 1:1 的比例,并且应该非常快。

SELECT 
      u1.firstname,
      u1.lastname,
      u1.totalcommission,
      u1.userid,
      PreAggUA1.AffiliateUsers as Level1,
      PreAggUA2.AffiliateUsers as Level2
   FROM 
      ( select 
              ua1.affiliate1,
              count(*)  as AffiliateUsers
           from users ua1
              join users ua1b
                  on ua1.affiliate1 = ua1b.userid
                 and ua1b.userTypeID != '1'
              group by
                 ua1.affiliate1 ) as PreAggUA1

         JOIN Users u1
            on PreAggUA1.Affiliate1 = u1.UserID

         LEFT JOIN ( select 
                           ua2.affiliate2,
                           count(*)  as AffiliateUsers
                        from 
                           users ua2
                              join users ua2b
                                 on ua2.affiliate2 = ua2b.userid
                                and ua2b.userTypeID != '1'
                         group by
                            ua2.affiliate2 ) as PreAggUA2
            on PreAggUA1.Affiliate1 = PreAggUA2.Affiliate2
   ORDER BY 
      PreAggUA1.AffiliateUsers DESC
于 2013-04-02T10:57:15.867 回答