我有两张桌子。一个是记录呼叫的呼叫历史记录表(开始时间,结束时间,电话号码,用户等)。另一个是订单表,记录订单详细信息(订单号,客户信息,订单日期等)。创建呼叫时并不总是创建订单,因此没有保证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
答案 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')
这应该快得多......假设您的初始表中有任何可以查询的索引。