MySQL MAX_JOIN_SIZE错误

时间:2013-12-17 01:33:48

标签: mysql

我有两张桌子。一个是记录呼叫的呼叫历史记录表(开始时间,结束时间,电话号码,用户等)。另一个是订单表,记录订单详细信息(订单号,客户信息,订单日期等)。创建呼叫时并不总是创建订单,因此没有保证ID可以匹配它们。现在,我有兴趣白天获得总数。当我尝试运行查询以在一天之前对呼叫和加入订单进行求和时,我收到以下错误:

The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay

这是我使用的查询:

SELECT
    DATE_FORMAT(c.date_call_start,'%Y-%m-%d') as date,
    COUNT(c.id) as calls,
    COUNT(o.id) as orders

FROM tbl_calls c
    LEFT OUTER JOIN tbl_orders o 
    ON DATE_FORMAT(c.date_call_start,'%Y-%m-%d')  =  DATE_FORMAT(o.created,'%Y-%m-%d') 

WHERE c.campaign_id = 1 
    AND DATE_FORMAT(c.date_call_start,'%Y-%m-%d') = '2013-12-09'

GROUP BY DATE_FORMAT(c.date_call_start,'%Y-%m-%d')

即使某一天只有几个电话,它仍会显示相同的错误。所以我很确定我的查询需要工作。

我也尝试了一个子查询,但这不会汇总子查询中的总数。

SELECT

    DATE_FORMAT(c.date_call_start,'%Y-%m-%d') as date,
    count(c.id) as calls,
    (select count(DISTINCT o.id)
                    FROM tbl_orders o
                    WHERE DATE_FORMAT(o.created,'%Y-%m-%d') = DATE_FORMAT(c.date_call_start,'%Y-%m-%d')
                ) as orders

FROM tb_calls c

WHERE c.campaign_id = 1 
    AND DATE_FORMAT(c.date_call_start,'%Y-%m-%d') BETWEEN '2013-12-09' AND '2013-12-15'

GROUP BY DATE_FORMAT(c.date_call_start,'%Y-%m-%d')
WITH ROLLUP

有关如何使此查询生效的任何想法?最终我想得到如下结果,所以我可以做其他计算,比如%order等。

date         |  calls   |    orders
------------------------------------
2013-12-01   |       100|       10
2013-12-02   |       125|       20
NULL         |       225|       30

更新: 根据答案,我做了以下几点: 创建了带有日期字段(无日期时间)的call_date字段到tbl_calls 创建了date_order字段,其日期格式(不是日期时间)为tbl_orders 更新了每个表,并将新字段设置为= date_format(the_date_time_stamp,'%Y-%m-%d')来自同一个表。 还为每个新日期字段添加了索引。

这使得以下查询起作用:

SELECT
    c.call_date as date,
    COUNT(DISTINCT c.id) as calls,
    COUNT(DISTINCT o.id) as orders,
    ROUND((COUNT(DISTINCT o.id) / COUNT(DISTINCT c.id))*100,2) as conversion

FROM tbl_calls c
 JOIN tbl_orders o 
    ON c.call_date  =  o.date_order

WHERE c.campaign_id = 1 
    AND c.call_date BETWEEN '2013-12-09' AND '2013-12-15' 

GROUP BY c.call_date
WITH ROLLUP

这给了我以下结果,我可以建立起来。感谢各位提出建议的人。我试过各个。一切都有道理。但是,由于我最终必须创建其他日期字段,我选择了

的答案
date         | calls  | orders| conversion
-------------------------------------------
2013-12-09   |  151   | 6     | 3.97
2013-12-10   |  164   | 2     | 1.22
2013-12-11   |  165   | 6     | 3.64
2013-12-12   |  189   | 1     | 0.53
2013-12-13   |  116   | 4     | 3.45
null         |  785   | 19    | 2.42

3 个答案:

答案 0 :(得分:1)

首先 - 尝试EXPLAIN SELECT....的结果,其中...是上面选择查询的其余部分。

由于您在两个已应用函数的字段上执行连接 - 我猜测并且说MySQL正在执行两次全表扫描并使用类型all进行连接。请参阅EXPLAIN输出的this for an explanation

DATE_FORMAT(c.date_call_start,'%Y-%m-%d')  =  DATE_FORMAT(o.created,'%Y-%m-%d')

您很可能希望在每个表中创建一个单独的字段,该字段仅包含DATE_FORMAT调用的结果。然后为每个新字段创建一个索引。然后加入这些新的索引字段。 MySQL应该更好。

答案 1 :(得分:1)

据推测,您想要计算每个日期的来电和订单。但是,这不是您的查询所做的,因为它会为给定日期的所有订单创建笛卡尔积。

相反,首先按日期汇总数据,然后合并结果。这可能是你想要的:

select c.date, calls, orders
from (select DATE_FORMAT(c.date_call_start, '%Y-%m-%d') as date, count(*) as calls
      from tbl_calls c
      WHERE c.campaign_id = 1 and
            DATE_FORMAT(c.date_call_start, '%Y-%m-%d') = '2013-12-09'
      group by DATE_FORMAT(c.date_call_start, '%Y-%m-%d')
     ) c left outer join
     (select DATE_FORMAT(o.created,'%Y-%m-%d') as date, count(*) as orders
      from tbl_orders o
      group by DATE_FORMAT(o.created, '%Y-%m-%d')
     ) o
     on c.date = o.date;

答案 2 :(得分:1)

如果@Barmar的建议不起作用,那么您可能需要将字段拆分为DATE和TIME。

另一个方向是制作两个临时表(给你三个查询:

CREATE TEMPORARY TABLE `tbl_calls_temp`  SELECT *  FROM tbl_calls c WHERE DATE(c.date_call_start) = '2013-12-09' AND c.campaign_id = 1

然后对tbl_orders TABLE

执行相同的限制
CREATE TEMPORARY TABLE `tbl_orders_temp` SELECT * FROM tbl_orders o WHERE DATE(o.created) = '2013-12-09'

最后查询两个临时表。根据您获得的数据量,您可能希望将索引添加到临时表中......但很可能您正面临完全加入

SELECT
    DATE_FORMAT(c.date_call_start,'%Y-%m-%d') as date,
    COUNT(c.id) as calls,
    COUNT(o.id) as orders

FROM tbl_calls_temp c
    LEFT OUTER JOIN tbl_orders_temp o 
    ON DATE_FORMAT(c.date_call_start,'%Y-%m-%d')  =  DATE_FORMAT(o.created,'%Y-%m-%d') 
GROUP BY DATE_FORMAT(c.date_call_start,'%Y-%m-%d')

这应该快得多......假设您的初始表中有任何可以查询的索引。