2009-06-22 10 views
6

je l'ensemble suivant des dates (jj/mm/aaaa) correspondant à des événements dans ma base de données:Calculer les plages de dates manquants et des plages de dates qui se chevauchent entre deux dates

 
eventId  startDate  endDate 
1   02/05/2009 10/05/2009 
2   08/05/2009 12/05/2009 
3   10/05/2009 12/05/2009 
4   21/05/2009 21/05/2009 
5   25/05/2009 NULL 
6   01/06/2009 03/06/2009 

Les événements ont un début et une date de fin (les temps n'ont pas d'importance) et une valeur endDate NULL signifie que l'événement est toujours en cours. Ce que je voudrais déterminer est les plages de dates entre deux dates arbitraires où il y avait a) aucun événement et b) les événements se chevauchaient.

Donc, pour une plage de dates d'entrée 01/04/2009 - 30/06/2009 j'attendre d'avoir les résultats suivants:

 
no event: 01/04/2009 - 01/05/2009 
overlap : 08/05/2009 - 10/05/2009 
overlap : 10/05/2009 - 12/05/2009 
no event: 13/05/2009 - 20/05/2009 
no event: 22/05/2009 - 24/05/2009 
overlap : 01/06/2009 - 03/06/2009 

Notez que les deux plages de chevauchement adjacentes seraient acceptables comme un résultat.

Quelqu'un peut-il s'il vous plaît m'aider avec un algorithme SQL pour générer cet ensemble de résultats?

EDIT: La base de données de la plate-forme cible est SQL Server 2005. Les dates sont enregistrées en tant que 10/05/2009 00:00:00, ce qui signifie que l'événement s'est terminé entre le 05/05/2009 00:00:00 et 05/10/2009 23:59:59. La même chose est vraie pour les dates de début. La plage de dates d'entrée peut donc être lue comme 01/04/2009 00:00:00 - 30/06/2009 23:59:59.

+1

Sur quelle plate-forme de base de données (s) vous exécuter cette requête? –

Répondre

4

Il est une petite variation de la fonction pour aplatir plages temporelles se croisent dans SQL Server:

Il est l'un des rares cas où l'approche fondée sur un curseur dans SQL Server est plus rapide l'un à base de série:


CREATE FUNCTION mytable(@p_from DATETIME, @p_till DATETIME) 
RETURNS @t TABLE 
     (
     q_type VARCHAR(20) NOT NULL, 
     q_start DATETIME NOT NULL, 
     q_end DATETIME NOT NULL 
     ) 
AS 
BEGIN 
     DECLARE @qs DATETIME 
     DECLARE @qe DATETIME 
     DECLARE @ms DATETIME 
     DECLARE @me DATETIME 
     DECLARE cr_span CURSOR FAST_FORWARD 
     FOR 
     SELECT startDate, endDate 
     FROM mytable 
     WHERE startDate BETWEEN @p_from AND @p_till 
     ORDER BY 
       startDate 
     OPEN cr_span 
     FETCH NEXT 
     FROM cr_span 
     INTO @qs, @qe 
     SET @ms = @qs 
     SET @me = @qe 
     WHILE @@FETCH_STATUS = 0 
     BEGIN 
       FETCH NEXT 
       FROM cr_span 
       INTO @qs, @qe 
       IF @qs > @me 
       BEGIN 
         INSERT 
         INTO @t 
         VALUES ('overlap', @ms, @me) 
         INSERT 
         INTO @t 
         VALUES ('gap', @me, @qs) 
         SET @ms = @qs 
       END 
       SET @me = CASE WHEN @qe > @me THEN @qe ELSE @me END 
     END 
     IF @ms IS NOT NULL 
     BEGIN 
       INSERT 
       INTO @t 
       VALUES (@ms, @me) 
     END 
     CLOSE cr_span 
     RETURN 
END 
GO 

Cette fonction comprime chaque ensemble contigu de plages d'intersection dans une plage et renvoie à la fois la plage et l'intervalle suivant.

+0

La réponse de Quassnoi est-elle une solution au problème? si oui, quel est le nom de la table de données dans la fonction. –

+0

+1 Merci ....... –

1

Sans vraiment comprendre ce problème que vous essayez de résoudre, voici ma solution à un problème du haut de ma tête:

  1. Créer fonction de table (UDF) « toutes les dates » qui serait retourner toutes les dates dans une année.
  2. Convertissez vos événements en dates distinctes (une ligne d'événement deviendra autant de lignes qu'il y a de jours) par des événements de jointure interne à toutes les dates where the date is between event's start and end dates ... Conserver l'ID d'événement original.
  3. Faites une jointure externe de dates d'événements avec toutes les dates (à nouveau) pour trouver les écarts ou les échecs.
  4. Joignez-vous à des événements-dates avec where dates are same but eventId is not pour trouver des chevauchements.
0

mes pauvres, avec postgresql, vous pouvez le faire simplement:

(start1, end1) CHEVAUCHEMENTS (start2, sens2) (start1, length1) recouvre (start2, LENGTH2)

Cette expression donne vrai lorsque deux périodes (définies par leurs extrémités) se chevauchent, fausses lorsqu'elles ne se chevauchent pas. Les extrémités peuvent être spécifiées sous la forme de paires de dates, d'heures ou d'horodatages; ou comme date, heure ou horodatage suivi d'un intervalle. SELECT (DATE '2001-02-16', DATE '2001-12-21') CHEVAUCHEMENTS (DATE '2001-10-30', DATE '2002-10-30'); Résultat: vrai SELECT (DATE '2001-02-16', INTERVAL '100 jours') CHEVAUCHEMENTS (DATE '2001-10-30', DATE '2002-10-30'); Résultat: false

mais sous sql server, je ne sais pas ... désolé

Questions connexes