我有一个表(call_history)和一个电话呼叫列表报告,caller_id是呼叫者,start_date(DATETIME)是呼叫日期。我需要制作一份报告,说明每天有多少人第一次打电话。例如:
2013-01-01 - 100
2013-01-02 - 80
2013-01-03 - 90
我有这个完美的查询,但它很慢。 start_date和caller_id列都有索引;是否有其他方法可以获取此信息以加快处理速度?
以下是查询:
SELECT SUBSTR(c1.start_date,1,10), COUNT(DISTINCT caller_id)
FROM call_history c1
WHERE NOT EXISTS
(SELECT id
FROM call_history c2
WHERE SUBSTR(c2.start_date,1,10) < SUBSTR(c1.start_date,1,10)
AND c2.caller_id=c1.caller_id)
GROUP BY SUBSTR(start_date,1,10)
ORDER BY SUBSTR(start_date,1,10) desc
答案 0 :(得分:5)
以下“WHERE SUBSTR(c2.start_date,1,10)”正在破坏你的索引(你不应该在where子句的左侧执行函数)
请尝试以下方法:
SELECT DATE(c1.start_date), COUNT(caller_id)
FROM call_history c1
LEFT OUTER JOIN call_history c2 on c1.caller_id = c2.caller_id and c2.start_date < c1.start_date
where c2.id is null
GROUP BY DATE(start_date)
ORDER BY start_date desc
同时重新阅读你的问题,我认为这是另一种不使用NOT EXISTS的写作方式
SELECT DATE(c1.start_date), COUNT(DISTINCT c1.caller_id)
FROM call_history c1
where start_date =
(select min(start_date) from call_history c2 where c2.caller_id = c1.caller_id)
GROUP BY DATE(start_date)
ORDER BY c1.start_date desc;
答案 1 :(得分:2)
你做的很奇怪 - 使用WHERE
,GROUP
和ORDER
条款中的函数。当函数应用于计算条件时,MySQL 永远不会使用索引。因此,您无法对此查询执行任何操作,但为了改善您的情况,您应该更改表格结构并将日期存储为DATE
列(和单列)。然后按此列创建索引 - 在此之后,您将获得更好的结果。
答案 2 :(得分:0)
尝试用左外连接替换NOT EXISTS。
答案 3 :(得分:0)
好的,这是理想的解决方案, 速度现在是0.01
SELECT first_call_date, COUNT(caller_id) AS caller_count
FROM (
SELECT caller_id, DATE(MIN(start_date)) AS first_call_date
FROM call_history
GROUP BY caller_id
) AS ch
GROUP BY first_call_date
ORDER BY first_call_date DESC