多个左连接的MySQL COUNT - 优化

时间:2011-12-16 16:34:46

标签: mysql sql

我有一个查询,它通过使用LEFT JOIN和子查询从多个表中获取计数。我们的想法是计算会员参与的各种活动。

架构如下所示:

构件 PK member_id

表1 PK tbl1_id FK member_id

表2 PK tbl2_id FK member_id

表3 PK tbl3_id FK member_id

我的查询如下:

SELECT t1.num1,t2.num2,t3.num3
FROM member m
LEFT JOIN
(
   SELECT member_id,COUNT(*) as num1
   FROM table1
   GROUP BY member_id
) t1 ON t1.member_id = m.member_id
LEFT JOIN
(
   SELECT member_id,COUNT(*) as num2
   FROM table2
   GROUP BY member_id
) t2 ON t2.member_id = m.member_id
LEFT JOIN
(
   SELECT member_id,COUNT(*) as num3
   FROM table3
   GROUP BY member_id
) t3 ON t3.member_id = m.member_id
WHERE m.member_id = 27

其中27是测试ID。实际查询连接三个以上的表,并且在更改member_id的情况下多次运行查询。问题是这个查询运行得很慢。我得到了我需要的信息,但我想知道是否有人可以提出一种优化方法。非常感谢任何建议。非常感谢。

3 个答案:

答案 0 :(得分:3)

您应该重构您的查询。您可以通过重新排序查询收集数据的方式来执行此操作。怎么样?

  • 首先应用WHERE子句
  • 最后应用JOIN

这是您的原始查询:

SELECT t1.num1,t2.num2,t3.num3 
FROM member m 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num1 
   FROM table1 
   GROUP BY member_id 
) t1 ON t1.member_id = m.member_id 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num2 
   FROM table2 
   GROUP BY member_id 
) t2 ON t2.member_id = m.member_id 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num3 
   FROM table3 
   GROUP BY member_id 
) t3 ON t3.member_id = m.member_id 
WHERE m.member_id = 27 

这是你的新查询

SELECT
   IFNULL(t1.num1,0) num1,
   IFNULL(t1.num2,0) num2,
   IFNULL(t1.num3,0) num3
FROM
(
   SELECT * FROM member m 
   WHERE member_id = 27
) 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num1 
   FROM table1 
   WHERE member_id = 27
   GROUP BY member_id 
) t1 ON t1.member_id = m.member_id 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num2 
   FROM table2 
   WHERE member_id = 27
   GROUP BY member_id 
) t2 ON t2.member_id = m.member_id 
LEFT JOIN 
( 
   SELECT member_id,COUNT(*) as num3 
   FROM table3 
   WHERE member_id = 27
   GROUP BY member_id 
) t3 ON t3.member_id = m.member_id 
;

BTW我将member m更改为SELECT * FROM member m WHERE member_id = 27,以防您需要有关成员27的任何信息。我​​还在每个结果中添加IFNULL函数,以便在计数为NULL的情况下生成0。 / p>

你需要绝对确定

  • member_id是成员表的主键
  • member_id在table1,table2和table3
  • 中编入索引

试一试!!!

答案 1 :(得分:2)

在不知道您的架构以及您为索引做了什么的情况下,一种可行的方法是:

SELECT (select ifnull(count(*),0) from table1 where table1.member_id = m.id) as num1,
 (select ifnull(count(*),0) from table2 where table2.member_id = m.id) as num2,
 (select ifnull(count(*),0) from table3 where table3.member_id = m.id) as num3
from member m
WHERE m.member_id = 27

现在,这是一个稍微冒险的建议,仅仅是因为我对您的数据库或其他正在运行的内容或瓶颈所在的内容一无所知。

一般情况下,最好在您的查询中发布解释计划以获得更好的答案。

答案 2 :(得分:0)

SELECT num1, num2, count(*) as num3
FROM (
  SELECT member_id, num1, count(*) as num2
  FROM (
    SELECT member_id, count(*) as num1
    FROM member
    LEFT JOIN  table1 USING (member_id)
    WHERE member_id = 27) as m1
  LEFT JOIN table2 USING (member_id)) as m2
LEFT JOIN table3 USING (member_id);