I have a table (call_history) with a list of phone calls report, caller_id is the caller and start_date (DATETIME) is the call date. I need to make a report that will show how many people called for the first time for every day. For example:
2013-01-01 - 100
2013-01-02 - 80
2013-01-03 - 90
I have this query that does it perfectly, but it is very slow. There are indexes on both start_date and caller_id columns; is there an alternative way to get this information to speed the process up?
Here is the query:
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
The following "WHERE SUBSTR(c2.start_date,1,10)" is breaking your index (you shouldn't perform functions on the left hand side of a where clause)
Try the following instead:
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
Also re-reading your problem, I think this is another way of writing without using 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;
You are doing a weird thing - using functions in WHERE
, GROUP
and ORDER
clauses. MySQL will never use indexes when function was applied to calculate condition. So, you can not do anything with this query, but to improve your situation, you should alter your table structure and store your date as DATE
column (and single column). Then create index by this column - after this you'll get much better results.
尝试用左外连接替换 NOT EXISTS。
OK here is the ideal solution, speed is now 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.