2009-11-05 6 views
2

Dans une table SQL je garde les réservations pour diverses resouces, avec une colonne StartDate/EndDate:SQL obtenir les ID qui sont disponibles dans l'intervalle de temps donné pour X jours consécutifs

ResourceID, StartDate, EndDate 
----------------------------------- 
1   2009-01-01 2009-01-05 
1   2009-01-07 2009-01-10 
2   2009-01-03 2009-01-18 

J'ai besoin de produire une liste de toutes les ressources disponibles pendant au moins X jours consécutifs dans un intervalle de temps donné, soit du 2009-01-01 au 2009-01-20 et X = 5 jours consécutifs.

par ex. pour ResourceID = 1, le plus grand intervalle de temps disponible est 2009-01-10 => 2009-01-20 donc cela est admissible, mais pour ResourceID = 2, il n'y a pas de créneau disponible de 5 jours. il y a une disposition de l'un 2009-01-01 => 2009-01-03 et un autre à 2009-01-18 => 2009-01-20, ni assez longtemps

EDIT:

Basé sur le réponse de Quassnoi, j'ai ajouté quelques modifications pour gérer certains cas de bords: les ressources sans réservation, ou les réservations qui couvrent toute la période de recherche.

Cela ressemble au résultat final. Muchos gracias pour toute l'aide!

WITH avRows AS  (   
    SELECT a.ID as aid,startDate , endDate , ROW_NUMBER() OVER (PARTITION BY ResourceID ORDER BY endDate) AS rn 
    FROM tblResources a left outer join tblReservations b   
    on b.ResourceID = a.ID and (startDate BETWEEN '2009-01-01' AND '2009-01-20' OR endDate BETWEEN '2009-01-01' AND '2009-01-20') 
    where a.ID NOT IN (select distinct ResourceID from tblReservations where (startDate <'2009-01-01' AND endDate > '2009-01-20')) 
    )SELECT DISTINCT COALESCE(rs.aid, rp.aid) 

     FROM avRows rs FULL JOIN avRows rp ON rs.aid = rp.aid AND rp.rn = rs.rn - 1 
     WHERE DATEDIFF(day, COALESCE(rp.endDate , '2009-01-01'), COALESCE(rs.startDate , '2009-01-20')) >= 5 
+0

Avez-vous besoin de connaître la date précise, ou seulement celle-là est disponible? –

+0

Juste qu'un intervalle est disponible. Peu importe s'il y a plusieurs intervalles ou quand. – Radu094

Répondre

3
SELECT resourceID 
FROM mytable 
WHERE startDate BETWEEN '2009-01-01' AND '2009-01-20' 
     AND DATEDIFF(day, CASE WHEN endDate < '2009-01-20' THEN endDate ELSE '2009-01-20' END, startDate) >= 5 
UNION 
SELECT resourceID 
FROM mytable 
WHERE endDate BETWEEN '2009-01-01' AND '2009-01-20' 
     AND DATEDIFF(day, endDate, CASE WHEN startDate > '2009-01-01' THEN startDate ELSE '2009-01-01' END) >= 5 

Mise à jour:

Désolé, n'a pas remarqué vos dossiers signifient les ressources occupées, non ressources gratuites.

Essayez ceci:

WITH rows AS 
     (
     SELECT ResourceID, StartDate, EndDate, ROW_NUMBER() OVER (PARTITION BY ResourceID ORDER BY EndDate) AS rn 
     FROM mytable 
     WHERE StartDate BETWEEN '2009-01-01' AND '2009-01-20' 
       AND EndDate BETWEEN '2009-01-01' AND '2009-01-20' 
     ) 
SELECT DISTINCT COALESCE(rs.ResourceID, rp.ResourceID) 
FROM rows rs 
FULL JOIN 
     rows rp 
ON  rs.ResourceID = rp.ResourceID 
     AND rp.rn = rs.rn - 1 
WHERE DATEDIFF(day, COALESCE(rp.EndDate, '2009-01-01'), COALESCE(rs.StartDate, '2009-01-20')) >= 5 

Mise à jour 2:

explications et des tests de performance plus détaillées:

+0

Ça marche! Je voudrais qu'il y ait un bouton 'bisou ya'. M'a sauvé d'une nuit de misère – Radu094

Questions connexes