2012-08-16 5 views
1

J'ai une table de base de données avec Begindate (datetime) et Enddate (datetime). Cette table contient les durées d'activité. Maintenant, j'essaye de créer une fonction pour calculer la durée totale basée sur des activités qui ne se chevauchent pas dans un begindate-enddate spécifié.Calcul de la durée totale non chevauchante des dates-heures de début

Un exaple serait comme suit:

Je fais appel à cette fonction donnant les paramètres: beginDate = '2012-08-16 10:00' endDate = '2012-08-16 18:00 '

maintenant, disons que les données suivantes sont dans le tableau:

  1. commencent: '2012-08-15 10:00' end '2012-08-15 14:00'(total 4 heures)
  2. début: '2012-08-16 09:00' fin '2012-08-16 11: 00 '(total 2 heures)
  3. début:' 2012-08-16 10:30 'fin' 2012-08-16 10:45 '(total 15 minutes)
  4. début:' 2012-08-16 12 : 00 'fin' 2012-08-16 16:00 '(total 4 heures)
  5. début:' 2012-08-16 13:00 'fin' 2012-08-16 17:00 '(total 4 heures)
  6. début: '2012-08-16 16:30' fin '2012-08-16 16:45' (total 15 minutes)
  7. début: '2012-08-16 17:30' fin '2012- 08-16 20:00 '(total 2 heures et 30 minutes)

Maintenant, je voudrais ce qui suit à happe n:

  1. La première activité est en dehors de la période spécifiée et ne sera donc pas incluse.
  2. Correspondance partielle pour que cela revienne 1 heure.
  3. L'activité est dans la deuxième activité et ne sera donc pas incluse.
  4. 4 heures avec la période seront inclus.
  5. 1 heure sera incluse de 16h00 à 17h00
  6. L'activité ne sera pas incluse.
  7. Seulement 30 minutes sont à l'intérieur de la période spécifiée qui sera incluse.

Le total retourné sera: 6 heures et 30 minutes.

Si quelqu'un pouvait m'aider avec cela, je serais très reconnaissant! :)

Répondre

3

Il pourrait être plus facile de calculer les gammes manquantes et puis durées Soustraire période complète:

declare @begindate datetime = '20120816 10:00:00' 
declare @enddate datetime = '20120816 18:00:00' 

; with supplement as (
    select begindate, enddate 
    from daterangetable 
     -- overlapping ranges only 
    where begindate <= @enddate 
    and enddate >= @begindate 
    union all 
    -- empty start range to catch missing start intervals 
    select @begindate, @begindate 
    union all 
    -- empty end range to catch missing end intervals 
    select @enddate, @enddate 
) 
select datediff (minute, @begindate, @enddate) 
    - sum (datediff (minute, gapStart, gapEnd)) Minutes 
from 
(
    select max(d2.enddate) gapStart, 
     d1.begindate gapEnd 
    from supplement d1 
    cross join supplement d2 
     -- d2 range must start before d1 range 
    where d2.begindate < d1.begindate 
    group by d1.begindate 
     -- Range is completely covered if d2 ends after d1 begins 
     -- so it should be removed 
    having max(d2.enddate) < d1.begindate 
) missingRanges 

Two ranges overlap si fin de première est après le début du deuxième et le début du premier est avant la fin de deuxième. Voir le lien pour (beaucoup mieux) l'explication.

Si vous n'utilisez pas Sql Server 2005 ou plus récent, vous devrez déplacer le code à l'intérieur de with dans les tables dérivées pour le complément d1 et le complément d2.

And here is Sql Fiddle with example.

+0

Merci pour la réponse rapide! C'est exactement ce dont j'avais besoin. –

+0

@DaanVermeulen Content de pouvoir aider :-) –

Questions connexes