Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Pour club les rangs pour les jours de semaine

C'est plutôt compliqué. Voici une approche utilisant les fonctions de fenêtre.

Tout d'abord, utilisez le tableau des dates pour énumérer les dates sans week-end (vous pouvez également prendre des vacances si vous le souhaitez). Ensuite, développez les périodes en un jour par ligne, en utilisant une non-équijointure.

Vous pouvez ensuite utiliser une astuce pour identifier les jours consécutifs. Cette astuce consiste à générer un numéro séquentiel pour chaque identifiant et à le soustraire du numéro séquentiel des dates. Il s'agit d'une constante pour des jours consécutifs. La dernière étape est simplement une agrégation.

La requête résultante ressemble à ceci :

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;

MODIFIER :

Ce qui suit est la version sur ceci Violon SQL :

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;

Je pense que cela fonctionne, mais le tableau des dates ne contient pas toutes les dates.