Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

So überspringen Sie Überschneidungsintervalle in der folgenden Abfrage, um die genaue Streckenzeit pro Tag zu erhalten

Dies ist ein "Lücken und Inseln"-Problem. Ich habe meine eigenen Testdaten gefälscht (da Sie keine bereitgestellt haben), aber ich denke, es funktioniert. Die wichtigste Intuition ist, dass alle Werte innerhalb derselben „Insel“ (d. h. zusammenhängendes Zeitintervall) denselben Unterschied zu einer row_number()-Spalte aufweisen. Wenn Sie einen kleinen Einblick wünschen, führen Sie eine Rohauswahl aus IntervalsByDay durch cte (im Gegensatz zu der Unterabfrage, die ich jetzt habe); dies zeigt Ihnen die berechneten Inseln (mit Start- und Endpunkt).

Bearbeiten:Ich habe nicht gesehen, dass Sie beim ersten Mal eine Geige hatten. Meine Antwort wurde geändert, um Ihre Daten und die gewünschte Ausgabe widerzuspiegeln

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