Những điều sau đây dường như thực hiện thủ thuật:
SET @locationID=0,@ts=NULL,@changed=0;
SELECT
MIN(assetID) AS id
, MIN(locationID) AS location
, SUM(secDiff) AS duration
FROM
(SELECT
assetID
, locationID
, @changed := IF(locationID <> previousLocationID, @changed + 1, @changed) AS changed
, IFNULL(TIMESTAMPDIFF(SECOND,
previousTs,
ts
),
0
) AS secDiff
FROM
(SELECT
assetID
, locationID
, @locationID AS previousLocationID
, @locationID := locationID AS currentLocationID
, ts
, @ts AS previousTs
, @ts := ts AS currentTs
FROM Logs L1
WHERE assetid = 1157
ORDER BY ts
) L2
ORDER BY ts
) L3
GROUP BY changed
ORDER BY changed DESC
;
Xem nó trong thực tế: SQL Fiddle .
Cập nhật:
Nếu bạn cần tham gia các bảng bổ sung, bạn thực sự nên JOIN
và không chọn phụ. Vì có GROUP BY
ở cấp cao nhất hiện tại, câu lệnh hiện có cần được bao bọc trong một tập hợp các dấu ngoặc đơn khác - để ngăn việc nhóm qua các bảng dữ kiện. Với một số điều chỉnh khác hướng tới mục tiêu đó:
SET @locationID=0,@ts=NULL,@changed=0;
SELECT
A.name
, L4.assetID
, L.name
, L4.locationID
, duration
FROM
(SELECT
MIN(assetID) AS assetID
, MIN(locationID) AS locationID
, SUM(secDiff) AS duration
, changed
FROM
(
-- no change in here
) L3
GROUP BY changed
) L4
JOIN Asset A
ON L4.assetID = A.id
JOIN Location L
ON L4.locationID = L.id
ORDER BY changed DESC
;
Mở rộng SQL Fiddle .
Cập nhật 2:
Cách đơn giản nhất để giải quyết các danh sách trùng lặp là DISTINCT
chúng đi ngay từ bước đầu tiên:
-- no change here
(SELECT
assetID
, locationID
, @locationID AS previousLocationID
, @locationID := locationID AS currentLocationID
, ts
, @ts AS previousTs
, @ts := ts AS currentTs
FROM
(SELECT DISTINCT
assetID
, locationID
, ts
FROM Logs
WHERE assetid = 1157
) L1
ORDER BY ts
) L2
-- no change here either
SQL Fiddle này trả về cho Nhật ký trùng lặp dữ liệu được đặt cùng kết quả với SQL Fiddle , nơi truy vấn trước đó chạy dựa trên dữ liệu không có bản sao.
Vui lòng nhận xét, nếu và vì điều này cần điều chỉnh / chi tiết thêm.