2013-07-31 19 views
-1

我有3个表:修复SQL查询,使其变得更有效率

  1. mobile_users - 与idphone_type,...

2 + 3。 iphone_purchasesandroid_purchases - 与idstatususer_id,..

我试图让所有谁做2名或购买更多的用户。 成功购买确定status > 0。 另外,我打算在同一查询中获取mobile_users表中的用户总数。

这是我想出了查询:

SELECT COUNT(*) AS `users`, 
     (SELECT COUNT(*) 
      FROM `mobile_users` 
     ) AS `total` 
    FROM `mobile_users` 
WHERE `mobile_users`.`phone_type` = 'iphone' 
    AND (SELECT COUNT(*) 
      FROM (SELECT `status`, 
         `user_id` 
        FROM `iphone_purchases` 
        UNION 
        SELECT `status`, 
         `user_id` 
        FROM `android_purchases` 
       ) AS `purchase_list` 
      WHERE `purchase_list`.`status` > 0 
      AND `purchase_list`.`user_id` = `mobile_users`.`id` 
     ) >= 2 

这是非常慢的,我必须找到一个方法来改善它。 任何帮助,将不胜感激!

编辑: 另外,你应该考虑到我在PHP中使用子查询构建这个查询。 我在WHERE语句中使用更多条件构建它。

+1

为什么要将iphone/android存储在单独的表中? –

+0

选择拥有2个或更多iphone + android购买的iphone用户总数,并在用户总数旁边显示此数字.... iPhone用户甚至可以出现在android_purchases数据库中吗? – JustinDanielson

+0

**您需要向我们展示表格和索引定义**以及每个表格的行数。也许你的表格定义不好。也许索引没有正确创建。也许你没有一个你认为你做过的那个专栏的索引。没有看到表和索引定义,我们不能说。我们还需要行计数,因为这会大大影响查询优化。如果你知道如何做一个'EXPLAIN'或者得到一个执行计划,那就把结果也放在问题中。 –

回答

3

您的查询只是返回用户数,而不是每个用户。

以下重构您的查询。它分别计算iphones和androids的购买次数,然后使用left outer join进行合并。 where条款简单地结合了计数:

select mu.*, i.cnt as iphones, a.cnt as androids 
from mobile_users mu left outer join 
    (SELECT `user_id`, count(*) as cnt 
     FROM `iphone_purchases` 
     where `status` > 0 
     group by user_id 
    ) i 
    on i.user_id = mu.id left outer join 
    (SELECT `user_id`, count(*) as cnt 
     FROM `android_purchases` 
     where `status` > 0 
     group by user_id 
    ) a 
    on a.user_id = mu.id 
where coalesce(i.cnt, 0) + coalesce(a.cnt, 0) >= 2; 
+0

如果非空,coalesce(i.cnt,0)是否返回cnt,否则为0?在列列表中合并是否合适? – JustinDanielson

+0

@JustinDanielson。 。 。如果第一个参数是NULL,那么coalesce()会返回第二个参数(并且它可能需要两个以上的参数)。至于'select'。 。是的,如果你愿意看到“0”而不是“NULL”,那么在那里做也是有意义的。 –