sql >> Base de Datos >  >> RDS >> PostgreSQL

Suma de la diferencia de tiempo entre filas

La dificultad especial es no perder los lapsos de tiempo hasta el marco de tiempo exterior.
Suponiendo que la siguiente fila para cualquier id dado siempre tiene el estado opuesto.
Usando el nombre de columna ts en lugar de recordTime :

WITH span AS (
   SELECT '2014-03-01 13:00'::timestamp AS s_from  -- start of time range
        , '2014-03-01 14:00'::timestamp AS s_to    -- end of time range
   )
, cte AS (
   SELECT id, ts, status, s_to
        , lead(ts, 1, s_from) OVER w AS span_start
        , first_value(ts)     OVER w AS last_ts
   FROM   span s
   JOIN   tbl  t ON t.ts BETWEEN s.s_from AND s.s_to
   WINDOW w AS (PARTITION BY id ORDER BY ts DESC)
   )
SELECT id, sum(time_disconnected)::text AS total_disconnected
FROM  (
   SELECT id, ts - span_start AS time_disconnected
   FROM   cte
   WHERE  status = 'Connected'

   UNION  ALL  
   SELECT id, s_to - ts
   FROM   cte
   WHERE  status = 'Disconnected'
   AND    ts = last_ts
   ) sub
GROUP  BY 1
ORDER  BY 1;

Devuelve los intervalos solicitados.
Los ID sin entradas en el intervalo de tiempo seleccionado no aparecen. Tendrías que consultarlos adicionalmente.

SQL Fiddle.
Nota:Lanzo el resultado total_disconnected a text en el violín, porque el tipo interval se muestra en un formato terrible.

Añadir ID sin entrada en el marco de tiempo seleccionado


Agregue a la consulta anterior (antes del ORDER BY 1 final ):

...
UNION  ALL
SELECT id, total_disconnected
   FROM  (
   SELECT DISTINCT ON (id)
          t.id, t.status, (s.s_to - s.s_from)::text AS total_disconnected
   FROM   span     s
   JOIN   tbl      t ON t.ts < s.s_from  -- only from before time range
   LEFT   JOIN cte c USING (id)
   WHERE  c.id IS NULL         -- not represented in selected time frame
   ORDER  BY t.id, t.ts DESC   -- only the latest entry
   ) sub
WHERE  status = 'Disconnected' -- only if disconnected
ORDER  BY 1;

SQL Fiddle.

Ahora, solo identificaciones sin entradas en o antes el intervalo de tiempo seleccionado no aparece.