使用左连接优化多个表上的SQL查询

时间:2014-07-01 13:03:05

标签: mysql sql

我已经创建了一个自定义的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

2 个答案:

答案 0 :(得分:1)

该时段内每位用户有多少个电话/电子邮件/任务?这个查询实际上是对结果进行交叉连接,所以如果每个用户有(比方说)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的检查不是绝对必要的,但应该加快速度。

答案 1 :(得分:0)

我看到你之后加入表格并过滤。例如:

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

通过这种方式,您可以显着减少加入表格所需的时间。