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

Um die Reihen für Wochentage zu schlagen

Das ist ziemlich kompliziert. Hier ist ein Ansatz mit Fensterfunktionen.

Verwenden Sie zunächst die Datumstabelle, um die Daten ohne Wochenenden aufzuzählen (Sie können auch Feiertage herausnehmen, wenn Sie möchten). Erweitern Sie dann die Zeiträume auf einen Tag pro Zeile, indem Sie einen Non-Equijoin verwenden.

Sie können dann einen Trick anwenden, um aufeinanderfolgende Tage zu identifizieren. Dieser Trick besteht darin, für jede ID eine fortlaufende Nummer zu generieren und sie von der fortlaufenden Nummer für die Daten zu subtrahieren. Dies ist eine Konstante für aufeinanderfolgende Tage. Der letzte Schritt ist einfach eine Aggregation.

Die resultierende Abfrage sieht in etwa so aus:

with d as (
      select d.*, row_number() over (order by date) as seqnum
      from dates d
      where day not in ('Saturday', 'Sunday')
     )
select t.id, min(t.date) as startdate, max(t.date) as enddate, sum(duration)
from (select t.*, ds.seqnum, ds.date,
             (d.seqnum - row_number() over (partition by id order by ds.date) ) as grp
      from table t join
           d ds
           on ds.date between t.startdate and t.enddate
     ) t
group by t.id, grp;

BEARBEITEN:

Das Folgende ist die Version auf diesem SQL-Geige:

with d as (
      select d.*, row_number() over (order by date) as seqnum
      from datetable d
      where day not in ('Saturday', 'Sunday')
     )
select t.id, min(t.date) as startdate, max(t.date) as enddate, sum(duration)
from (select t.*, ds.seqnum, ds.date,
             (ds.seqnum - row_number() over (partition by id order by ds.date) ) as grp
      from (select t.*, 'abc' as id from table1 t) t join
           d ds
           on ds.dateid between t.startdate and t.enddate
     ) t
group by grp;

Ich glaube, das funktioniert, aber die Datumstabelle enthält nicht alle Daten.