Ten powinien działać, ale jest prawdziwym zabójcą wydajności!
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
podaje prawidłowe odpowiedzi dla przykładowych danych. Oto, jak to działa:
- Najbardziej wewnętrzna część (
a.calldate<=b.calldate AND (UNIX_TIMESTAMP(a.calldate)+a.duration)>=UNIX_TIMESTAMP(b.calldate)
...) oblicza przecięcie:Dwie zapowiedzi nakładają się, jeśli punkt początkowy jednego zawiadomienia znajduje się w punkcie początkowym drugiego zawiadomienia lub za nim oraz w punkcie końcowym tego zawiadomienia lub przed nim - Samodzielne łączenie tabel wywołań powoduje znalezienie wszystkich nakładających się elementów,
- ale z problemem:self join znajduje zachodzenie na siebie między liniami 1 i 2, ale inne z liniami 2 i 1. Jeśli więcej niż dwa wywołania nakładają się, jest to żmudne, aby rozwiązać ten problem
- Teraz, ponieważ Twoje dane zawierają unikalny numeryczny identyfikator, możemy go użyć do filtrowania tych duplikatów, potrójnych kopii itp. Odbywa się to za pomocą
AND a.uniqueid>b.uniqueid
selektor iGROUP BY a.uniqueid
, co sprawia, że tylko wywołanie z najmniejszym unikalnym identyfikatorem widzi wszystkie równoczesne wywołania, a inne widzą mniej - Korzystanie z
MAX()
na tym w zewnętrznym zapytaniu odfiltrowuje ten rekord - Potrzebujemy
+1
aby uzyskać szczytową liczbę połączeń:Połączenie z 2 równoczesnymi połączeniami oznacza szczytową liczbę 3