2013-07-31 17 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」,那麼在那裏做也是有意義的。 –