簡體   English   中英

使用左聯接在多個表上優化SQL查詢

[英]Optimization of an SQL Query on multiple tables with Left joins

我創建了一個自定義的mysql查詢,該查詢運行良好並且顯示了我想要的輸出,但是由於數據量很大,當前需要花費很多時間。

因此,請幫助我優化查詢運行時間。

SELECT t.*, te + tc + tt AS total, (te + tc + tt)/7 AS weekly_Avg
FROM (SELECT t2.first_name, COUNT(DISTINCT emails.id) AS te,
        COUNT(DISTINCT calls.id) AS tc, COUNT(DISTINCT tasks.id) AS tt
      FROM users AS t2
      LEFT JOIN emails
        ON t2.id = emails.assigned_user_id
        AND emails.date_entered >= '2014-03-20 00:00:00'
        AND emails.date_entered <= '2014-06-30 00:00:00'
      LEFT JOIN calls
        ON t2.id = calls.assigned_user_id
        AND calls.date_entered >= '2014-03-20 00:00:00'
        AND calls.date_entered <= '2014-06-30 00:00:00'
      LEFT JOIN tasks
        ON t2.id = tasks.assigned_user_id
        AND tasks.date_entered >= '2014-03-20 00:00:00'
        AND tasks.date_entered <= '2014-06-30 00:00:00')
      WHERE t2.id IN ('1', '2')
      GROUP BY t2.id) t

每個用戶在這段時間內有多少個呼叫/電子郵件/任務? 該查詢實際上是對結果進行交叉聯接,因此,如果每個用戶每個有100個(例如)100個,即為每個用戶提供1000000條記錄,然后在該列表中挑選出唯一的記錄。

如果是這樣,使用子查詢來獲取每個計數並將結果結合在一起可能會更容易。

SELECT t . * ,te+tc+tt as total , (,te+tc+tt)/7 as weekly_Avg
FROM 
(
    SELECT t2.first_name, emails_count AS te, calls_count AS tc, tasks_count AS tt
    FROM  `users` AS t2
    LEFT JOIN 
    (
        SELECT assigned_user_id, COUNT( emails.id ) AS emails_count
        FROM emails 
        WHERE emails.assigned_user_id IN ( '1',  '2')
        AND (emails.date_entered >=  '2014-03-20 00:00:00' 
        AND emails.date_entered <=  '2014-06-30 00:00:00')
        GROUP BY assigned_user_id
    ) sub_emails
    ON t2.id = sub_emails.assigned_user_id
    LEFT JOIN 
    (
        SELECT assigned_user_id, COUNT( calls.id ) AS calls_count
        FROM calls 
        WHERE calls.assigned_user_id IN ( '1',  '2')
        AND (calls.date_entered >=  '2014-03-20 00:00:00' 
        AND calls.date_entered <=  '2014-06-30 00:00:00')
        GROUP BY assigned_user_id
    ) sub_calls
    ON t2.id = sub_calls.assigned_user_id
    LEFT JOIN 
    (
        SELECT assigned_user_id, COUNT( tasks.id ) AS tasks_count
        FROM tasks 
        WHERE tasks.assigned_user_id IN ( '1',  '2')
        AND (tasks.date_entered >=  '2014-03-20 00:00:00' 
        AND tasks.date_entered <=  '2014-06-30 00:00:00')
        GROUP BY assigned_user_id
    ) sub_tasks
    ON t2.id = sub_tasks.assigned_user_id
    WHERE t2.id IN ('1',  '2')
)t

注意,在子查詢中對user_id的檢查不是嚴格必需的,但是可以加快速度。

我看到您正在加入表格並隨后進行過濾。 例如:

SELECT t2.first_name, COUNT( DISTINCT emails.id ) AS te, COUNT( DISTINCT calls.id ) AS tc, COUNT( DISTINCT tasks.id ) AS tt
FROM  `users` AS t2
LEFT JOIN emails ON t2.id = emails.assigned_user_id
AND (

emails.date_entered >=  '2014-03-20 00:00:00'
AND emails.date_entered <=  '2014-06-30 00:00:00'
)

您應該這樣做:

SELECT t2.first_name, COUNT( DISTINCT emails.id ) AS te, COUNT( DISTINCT calls.id ) AS tc, COUNT( DISTINCT tasks.id ) AS tt
FROM  `users` AS t2
LEFT JOIN 
(SELECT FIELDS_YOU_NEED 
 FROM `emails` 
 WHERE date_entered >=  '2014-03-20 00:00:00' AND date_entered <=  '2014-06-30 00:00:00'
 ) AS emails2 

ON t2.id = emails2.assigned_user_id

這樣,您將大大減少連接表所花費的時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM