Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come saltare gli intervalli di sovrapposizione nella query seguente per ottenere il tempo di tracciamento giornaliero accurato

Questo è un problema di "lacune e isole". Ho falsificato i miei dati di test (poiché non ne hai forniti), ma penso che funzioni. L'intuizione chiave è che tutti i valori all'interno della stessa "isola" (cioè un intervallo di tempo contiguo) avranno la stessa differenza da una colonna row_number(). Se vuoi un po' di informazioni, fai una selezione grezza da IntervalsByDay cte (al contrario della sottoquery che ho ora); questo ti mostrerà le isole calcolate (con punti di inizio e fine).

modifica:non ho visto che avevi un violino al primo giro. La mia risposta è stata modificata per riflettere i tuoi dati e l'output desiderato

with i as (
    select datediff(minute, '2013-01-01', StartTime) as s,
        datediff(minute, '2013-01-01', EndTime) as e
    from #track
), brokenDown as (
    select distinct n.Number
    from i
    join dbadmin.dbo.Numbers as n
        on n.Number >= i.s
        and n.Number <= i.e
), brokenDownWithID as (
    select Number, Number - row_number() over(order by Number) as IslandID,
        cast(dateadd(minute, number, '2013-01-01') as date) as d
    from brokenDown
), IntervalsByDay as (
    select
        dateadd(minute, min(number), '2013-01-01') as [IntervalStart],
        dateadd(minute, max(number), '2013-01-01') as [IntervalEnd],
        d,
        max(Number) - min(Number) + 1 as [NumMinutes]
    from brokenDownWithID
    group by IslandID, d
)
select d, sum(NumMinutes) as NumMinutes
from IntervalsByDay
group by d
order by d