2017-04-11 40 views
0

我有4個表(1到很多): 不要說任何關於「電子郵件」關係。這是我的開發老闆多年前建立的。MYSQL堅持生成臨時表(海量查詢)

EMPLOYEES (+-50 results) 
------------------------------------------------ 
id name  
1  EmpName 1 
2  EmpName 2 

CUSTOMERS (+50k results) 
------------------------------------------------ 
id name email   employee_assigned 
1  John [email protected]  12 
2  Donald [email protected] 6 

INTERESTS_CATEGORIES (+650k results) 
------------------------------------------------ 
id customer_email category_id 
1  [email protected]  97 
2  [email protected]  13 
3  [email protected] 56 
4  [email protected] 126 
5  [email protected] 45 

INTERESTS_PRODUCTS (+650k results) 
------------------------------------------------ 
id customer_email product_id 
1  [email protected]  78 
2  [email protected]  23 
3  [email protected] 19 
4  [email protected] 56 
5  [email protected] 45 

所以我需要通過分配的員工和他們的興趣過濾客戶。 這裏是查詢:

SELECT 
    * 
FROM   
(
    SELECT 
     customers.id      AS 'id', 
     customers.name      AS 'first_name', 
     customers.email, 
     employees.id      AS 'employee_id' 
    FROM 
     customers, 
     employees 
    WHERE 
     employees.id = 2 
     AND 
     customers.employee_assigned = employees.id 
) AS myCustomers 

LEFT JOIN interests_categories 
    ON interests_categories.customer_email = myCustomers.email 
LEFT JOIN interests_products 
    ON interests_categories.customer_email = myCustomers.email 
WHERE  
( 
    interests_categories.category_id = 20 
    OR 
    interests_categories.category_id = 21 
) 

GROUP BY myCustomers.email 

那麼,問題:

  • 如果員工有分配的客戶數量較少(如3)查詢 是全成。

  • 如果員工擁有中等數量的指定客戶(超過100個)查詢夾具。

我執行SHOW PROCESSLIST,它是stucked 「生成臨時表」。

有人有想法嗎? :( 謝謝

+0

擺脫子查詢的,只是用加入。而不是where子句中的OR,使用IN。Last請確保您在每個表的電子郵件列上以及where或ON子句中使用的任何列上都有索引。 –

+0

我會盡力的。謝謝你的答案。 :) –

回答

0

檢查你的表的索引和嘗試這個辦法:。

SELECT 
    c.id AS 'id', 
    c.name AS 'first_name', 
    c.email, 
    e.id AS 'employee_id' 
    ic.*, 
    ip.* 
FROM customers c 
JOIN employees e 
ON c.employee_assigned = e.id 
LEFT JOIN interests_categories ic 
    ON ic.customer_email = c.email 
LEFT JOIN interests_products ip 
    ON ic.customer_email = c.email 
WHERE  
( 
    ic.category_id IN (20,21) 
    AND e.id = 2 
) 
GROUP BY myCustomers.email 
+0

充其量,在沒有聚合函數的查詢中包含GROUP BY子句是誤導。 – Strawberry

+0

那麼,我知道一些關於SQL的東西,但我不是主人。我的工作是php和jquery插件開發,但現在我一個人在這裏沒有SQL Master支持。所以,我發現一個超大的查詢不起作用。 (對我的英文是sry) –

+0

@Sloan,在電子郵件字段中添加索引是有效的,但適用於我的舊查詢,而不是您的查詢。要儘量讓你的工作,因爲我不顯示我想要的結果。 –

0

順便說一句,不太啞設計可能像下面這樣如果是我,我會先從這個,並提供適當的代表CREATE和INSERT語句也相應地,我很好奇,其中CATEGORY_ID來自 - 。因爲這可能爲進一步優化區域

EMPLOYEES 
------------------------------------------------ 
employee_id name  
      6 EmpName 1 
     12 EmpName 2 

CUSTOMERS 
------------------------------------------------ 
customer_id name email   employee_assigned 
      1 John [email protected]     12 
      2 Donald [email protected]     6 

INTERESTS_CATEGORIES 
------------------------------------------------ 
customer_id category_id 
      1   97 
      1   13 
      2   56 
      2   126 
      2   45 

INTERESTS_PRODUCTS 
------------------------------------------------ 
customer_id product_id 
      1   78 
      1   23 
      2   19 
      2   56 
      2   45 
+0

減啞設計?這意味着什麼?我在stackoverflow是相對新的。 category_id來自名稱關聯表。 category_id 1表示例如計算機,2類小孩玩具等。 –

+0

那麼,這會消除「電子郵件關係」,不是嗎?所以,不那麼愚蠢。 – Strawberry

+0

我不能這樣做。我告訴過,這是一個古老的大型數據庫。新客戶每1小時同步一次,但興趣是以繁瑣的過程插入的,所以當插入興趣時,您只知道電子郵件,而不知道ID。我必須與我所擁有的一起工作。我不能做出重大改變,因爲它可能會導致大的錯誤和浪費時間。 –