Điều này sẽ hoạt động, nhưng là một kẻ giết hiệu suất thực sự!
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 ra câu trả lời chính xác cho dữ liệu mẫu của bạn. Đây là cách hoạt động:
- Phần trong cùng (
a.calldate<=b.calldate AND (UNIX_TIMESTAMP(a.calldate)+a.duration)>=UNIX_TIMESTAMP(b.calldate)
...) tính giao điểm:Hai cuộc gọi trùng nhau, nếu điểm bắt đầu của một cuộc gọi nằm tại hoặc sau điểm bắt đầu của cuộc gọi kia và tại hoặc trước điểm kết thúc của cuộc gọi đó - Việc tự tham gia các bảng cuộc gọi sẽ tìm thấy tất cả các phần chồng chéo,
- nhưng có vấn đề:Tự kết hợp tìm thấy khoảng cách giữa các dòng 1 và 2, nhưng một liên kết khác có các dòng 2 và 1. Nếu có nhiều hơn hai lệnh gọi trùng nhau, thật tẻ nhạt khi sắp xếp điều này
- Bây giờ vì dữ liệu của bạn có chứa một ID duy nhất bằng số, chúng tôi có thể sử dụng ID này để lọc các bản sao, số ba, v.v. điều này được thực hiện bởi
AND a.uniqueid>b.uniqueid
bộ chọn vàGROUP BY a.uniqueid
, chỉ cuộc gọi có giá trị duy nhất nhỏ nhất mới xem được tất cả các cuộc gọi đồng thời, các cuộc gọi khác ít thấy hơn - Sử dụng
MAX()
về điều này trong truy vấn bên ngoài lọc ra hồ sơ này - Chúng tôi cần
+1
để có được tổng số cuộc gọi cao điểm:Một cuộc gọi có 2 cuộc gọi đồng thời có nghĩa là tổng số cuộc gọi cao điểm là 3