Lo siguiente parece funcionar:
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
;
Véalo en acción:SQL Fiddle .
Actualización:
Si necesita unirse a mesas adicionales, debería JOIN
y no sub-seleccionar. Como hay un GROUP BY
en el nivel más externo actualmente, la declaración existente debe estar envuelta en otro conjunto de paréntesis, para evitar la agrupación en las tablas de hechos. Con algunos otros ajustes hacia ese fin:
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
;
SQL Fiddle ampliado .
Actualización 2:
La forma más sencilla de abordar los listados duplicados debería ser DISTINCT
como primer paso:
-- 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
Este SQL Fiddle devoluciones para los Registros duplicados data el mismo conjunto de resultados que SQL Fiddle , donde la consulta anterior se ejecuta en datos sin duplicados.
Por favor comente, si y como esto requiere ajuste/más detalles.