Този трябва да работи, но е истински убиец на производителността!
SELECT
calldate,
MAX(concurrent)+1 AS peakcount
FROM (
SELECT
DATE(a.calldate) as calldate,
COUNT(b.uniqueid) AS concurrent
FROM cdr AS a, cdr AS b
WHERE
a.calldate BETWEEN '2013-11-08 00:00:00' AND '2013-11-13 23:59:59'
AND (
(a.calldate<=b.calldate AND (UNIX_TIMESTAMP(a.calldate)+a.duration)>=UNIX_TIMESTAMP(b.calldate))
OR (b.calldate<=a.calldate AND (UNIX_TIMESTAMP(b.calldate)+b.duration)>=UNIX_TIMESTAMP(a.calldate))
)
AND a.uniqueid>b.uniqueid
GROUP BY a.uniqueid
) AS baseview
GROUP BY calldate
дава правилните отговори за вашите примерни данни. Ето как работи:
- Най-вътрешната част (
a.calldate<=b.calldate AND (UNIX_TIMESTAMP(a.calldate)+a.duration)>=UNIX_TIMESTAMP(b.calldate)
...) изчислява пресичането:Две повиквания се припокриват, ако началната точка на едно повикване е на или след началната точка на другото повикване и на или преди крайната точка на това повикване - Самообединяването на таблиците на повикванията открива всички припокривания,
- но с проблем:Самосъединяването намира припокриване между редове 1 и 2, но друго с редове 2 и 1. Ако се припокриват повече от две извиквания, е досадно да се сортира това
- Сега, тъй като вашите данни съдържат цифров уникален идентификатор, можем да използваме това, за да филтрираме тези дубликати, три екземпляри и т.н. това се прави от
AND a.uniqueid>b.uniqueid
селектор иGROUP BY a.uniqueid
, което кара само повикването с най-малкия уникален идентификатор да вижда всички едновременни повиквания, останалите виждат по-малко - Използване на
MAX()
върху това във външната заявка филтрира този запис - Нуждаем се от
+1
за да получите пиковия брой повиквания:Обаждане с 2 едновременни повиквания означава пиков брой 3