none
Définir les bloc de jours qui se suivent

    Question

  • Bonjour,

    j'utilise SQL server 2008 et je souhaiterai effectuer l'opération suivante :

    - A partir d'une liste de date du même mois je souhaiterai récupérer la date de début et la date de fin d'un bloc de jour qui se suivent (en tenant compte des week end et des jours fériés).

    exemple : 
    01/03/2012, 02/03/2012, 05/03/2012, 06/03/2012, 20/03/2012 
    => le résultat attendu est : deux blocs, le 1er ayant comme date de début 01/03/2101, date de fin : 06/03/2012 (week end pris en compte).
    Le 2eme bloc ayant date de début 20/03/2012 et date de fin 20/03/2012.

    est il possible de réaliser cette requete en sql ?

    Merci d'avance
    mercredi 21 mars 2012 12:43

Réponses

  • Voila la solution pour ceux qui sont intéressé, il faut utiliser les curseurs,

    Solution : (Pour vérifier les jours férié j'ai créer une table qui s'appelle T_NOTWORKED  qui contient la liste des jours fériés)

                

    Create procedure test
    AS
    BEGIN
    Declare @idxDate as smalldatetime
    Declare @precDate as smalldatetime
    Declare @blockStartDate as smalldatetime
    Declare @nbDaysOff as tinyint

        -- pour les besoins de manipulation de date on fixe le 1er jour de la semaine au lundi
        SET DATEFIRST 1

        --Exemple : je remplie la table qui contient une liste de date
        CREATE TABLE #ListeDays(IMP_DATE smalldatetime)
        insert into #ListeDays values('2012-03-09')
        insert into #ListeDays values('2012-03-10')
        insert into #ListeDays values('2012-03-11')
        insert into #ListeDays values('2012-03-12')
        insert into #ListeDays values('2012-03-14')
        insert into #ListeDays values('2012-03-16')


        --Création de la table resultat temporaire
    CREATE TABLE #CONGES(
    DATE_DEBUT datetime,
    DATE_FIN datetime


    -- on récupère la liste des CP ou RTT
    Declare cursConges Cursor For 
    Select IMP_DATE
    From #ListeDays
    order by IMP_DATE


    Open cursConges
    Fetch Next From cursConges Into @idxDate

    -- init des bornes de tests de continuité
    Select @blockStartDate = @idxDate, @precDate = @idxDate

    While @@FETCH_STATUS = 0
    Begin
    -- on vérifie la continuité des dates
    If Day(@idxDate - @precDate)-1 <= 1
    Set @precDate = @idxDate
    Else
    Begin
    -- on vérifie si les journées de l'écart sont un we ou des jours férié
    While Day(@idxDate - @precDate) >= 2 
    Begin
    Set @precDate = @precDate + 1
    If DatePart("dw", @precDate) <= 5 And Not Exists(Select NWO_DATE From T_NOTWORKED Where NWO_DATE = @precDate)
    break
    Else
    Set @nbDaysOff = @nbDaysOff+1
    End
    End

    -- on vérifie s'il y a eu un écart de date
    If Day(@idxDate - @precDate) > 1
    Begin
    Insert Into #CONGES Select @blockStartDate, @precDate-1-@nbDaysOff 
    Select @blockStartDate = @idxDate, @precDate = @idxDate
    End
    Set @nbDaysOff = 0


    Fetch Next From cursConges Into @idxDate
    End
    Close cursConges
    Deallocate cursConges

    -- on ajoute éventuellement le dernier bloc
    if @blockStartDate <= @idxDate
    Insert Into #CONGES Select @blockStartDate, @idxDate


    -- on renvoie les résultats 
    SELECT * FROM #CONGES

    -- on supprime la table temporaire
    Drop Table #CONGES 

    END

     
    vendredi 23 mars 2012 13:43

Toutes les réponses

  • -- Table des intervalles 
    CREATE TABLE INTERVAL (IntervalDebut DATETIME, IntervalFin DATETIME, NumInterval INT)
    
    -- Remplissage de la table des intervales 
    DECLARE @DATEDEBUT DATETIME = '20120301' -- J'ai positionné la date de début sur le 01 mars 2012
    DECLARE @ID_INTERVAL INT = 1
    WHILE @DATEDEBUT < '20120401'
    BEGIN
    INSERT INTERVAL (IntervalDebut,IntervalFin,NumInterval)
    VALUES (@DATEDEBUT,DATEADD(day,7,@DATEDEBUT),@ID_INTERVAL)
    SET @DATEDEBUT = DATEADD(day,8,@DATEDEBUT);
    SET @ID_INTERVAL = @ID_INTERVAL +1
    END
    
    -- Table des listes de dates
    CREATE TABLE LIST_DATE(colDate DATETIME)
    INSERT INTO LIST_DATE VALUES ('20120301'),('20120302'),('20120305'),('20120306'),('20120320')
    
    -- Affichage des dates par intervale 
    SELECT i.IntervalDebut,i.IntervalFin,i.NumInterval,l.colDate
    FROM LIST_DATE l INNER JOIN INTERVAL i  ON i.IntervalDebut < l.colDate AND i.IntervalFin > l.colDate


    Etienne ZINZINDOHOUE - http://blog.developpez.com/zinzineti/



    • Modifié zinzineti mercredi 21 mars 2012 15:52
    mercredi 21 mars 2012 15:50
  • Merci pour ta réponse,

    peux être que je me suis mal exprimé,,, 

    je défini un bloc comme étant une succession de date, je redonne un autre exemple plus parlant :

    j ai la liste de date suivante :

    09/03/2012, 10/03/2012, 11/03/2012, 12/03/2012,  14/03/2012, 16/03/2012

    => le résultat est 3 bloc : 

    - le 1er bloc du 09 au 12 (le week end ne casse pas la notion de bloc vu que les jours se suivent, ça aurait été le cas si j'avais un jour férie)

    -le 2eme bloc du 14 au 14

    -le 3eme bloc du 16 au 16

    Merci encore pour ton aide

    mercredi 21 mars 2012 16:22
  •  

    Bonjour, Ours_blanc,

    Pouvez-vous svp nous expliquer qu’est-ce que vous voulez dire par blocs ? Ce n’est pas clair quel est le format du résultat  et où est ce résultat stocké (dans une table ? dans un variable ?).

    Bonne journée,

    Cipri


    Suivez MSDN sur Twitter   Suivez MSDN sur Facebook


    Ciprian DUDUIALA, MSFT  
    •Nous vous prions de considérer que dans le cadre de ce forum on n’offre pas de support technique et aucune garantie de la part de Microsoft ne peut être offerte.

    vendredi 23 mars 2012 09:37
  • Bjr Ciprian,

    Merci pour ton retour,

    le résultat attendu est une table.

    j'ai une liste de dates du même mois,  je souhaiterai regroupé ces date par bloc, 

    un bloc est défini comme étant une suite de dates (Day qui se succède : la différence entre deux date = 1 day)

    il faut noté aussi que le week end ou les un jour férié ne casse pas cette notion de bloc 

    je re explique mon exemple(vu plus haut) : supposant qu' on a la liste suivante

    ven 09/03/2012,  sam 10/03/2012,  dim 11/03/2012,  lun 12/03/2012,  mer 14/03/2012, ven 16/03/2012

    le premier bloc commence le 09/03 et se termine le 12/03 : remarque que le week end 10, 11 n'a pas cassé ce bloc

    les deux jours qui reste ne forme pas un seul bloc puisque y'a un creux entre les deux (le 15) => ce sont deux bloc différents, 

    ça aurait été un seul bloc si le 15/03 étais un jour férié.

    donc résultat final => 3 bloc 

    1er Bloc : date debut =  09/03/2012, datefin = 12/03/2012

    2eme Bloc : date debut =  14/03/2012, datefin = 14/03/2012

    3eme Bloc : date debut = 16/03/2012, datefin = 16/03/2012

    je ne sais si je suis clair ou pas

    Merci d'avance

    vendredi 23 mars 2012 11:05
  • Voila la solution pour ceux qui sont intéressé, il faut utiliser les curseurs,

    Solution : (Pour vérifier les jours férié j'ai créer une table qui s'appelle T_NOTWORKED  qui contient la liste des jours fériés)

                

    Create procedure test
    AS
    BEGIN
    Declare @idxDate as smalldatetime
    Declare @precDate as smalldatetime
    Declare @blockStartDate as smalldatetime
    Declare @nbDaysOff as tinyint

        -- pour les besoins de manipulation de date on fixe le 1er jour de la semaine au lundi
        SET DATEFIRST 1

        --Exemple : je remplie la table qui contient une liste de date
        CREATE TABLE #ListeDays(IMP_DATE smalldatetime)
        insert into #ListeDays values('2012-03-09')
        insert into #ListeDays values('2012-03-10')
        insert into #ListeDays values('2012-03-11')
        insert into #ListeDays values('2012-03-12')
        insert into #ListeDays values('2012-03-14')
        insert into #ListeDays values('2012-03-16')


        --Création de la table resultat temporaire
    CREATE TABLE #CONGES(
    DATE_DEBUT datetime,
    DATE_FIN datetime


    -- on récupère la liste des CP ou RTT
    Declare cursConges Cursor For 
    Select IMP_DATE
    From #ListeDays
    order by IMP_DATE


    Open cursConges
    Fetch Next From cursConges Into @idxDate

    -- init des bornes de tests de continuité
    Select @blockStartDate = @idxDate, @precDate = @idxDate

    While @@FETCH_STATUS = 0
    Begin
    -- on vérifie la continuité des dates
    If Day(@idxDate - @precDate)-1 <= 1
    Set @precDate = @idxDate
    Else
    Begin
    -- on vérifie si les journées de l'écart sont un we ou des jours férié
    While Day(@idxDate - @precDate) >= 2 
    Begin
    Set @precDate = @precDate + 1
    If DatePart("dw", @precDate) <= 5 And Not Exists(Select NWO_DATE From T_NOTWORKED Where NWO_DATE = @precDate)
    break
    Else
    Set @nbDaysOff = @nbDaysOff+1
    End
    End

    -- on vérifie s'il y a eu un écart de date
    If Day(@idxDate - @precDate) > 1
    Begin
    Insert Into #CONGES Select @blockStartDate, @precDate-1-@nbDaysOff 
    Select @blockStartDate = @idxDate, @precDate = @idxDate
    End
    Set @nbDaysOff = 0


    Fetch Next From cursConges Into @idxDate
    End
    Close cursConges
    Deallocate cursConges

    -- on ajoute éventuellement le dernier bloc
    if @blockStartDate <= @idxDate
    Insert Into #CONGES Select @blockStartDate, @idxDate


    -- on renvoie les résultats 
    SELECT * FROM #CONGES

    -- on supprime la table temporaire
    Drop Table #CONGES 

    END

     
    vendredi 23 mars 2012 13:43
  •  

    Bonjour,

    Bon, mais vu que les jours fériés sont différents d’un pays à l’autre et d’un an à l’autre il faut gérer cet aspect (dans une table ou par une fonction – voir aussi cette question). Comment pensez-vous le faire ?

    Il faut aussi gérer la liste des dates. Vous utilisez un string avec les dates séparées par ‘,’ donc vous pouvez utiliser les solutions proposées dans cette discussion ou dans cette discussion.

    Pour les week-ends c’est facile : vous pouvez utiliser la fonction DATEPART avec l’option weekday. Puis, pour voir si deux dates consécutives dans votre liste sont dans le même bloc utilisez DATEPART avec day : si les jours sont consécutifs c’est le même bloc, sinon il faut vérifier si les dates sont séparées par un week-end (avec weekday) ou par un jour férié.

    Bonne journée,

    Cipri


    Suivez MSDN sur Twitter   Suivez MSDN sur Facebook


    Ciprian DUDUIALA, MSFT  
    •Nous vous prions de considérer que dans le cadre de ce forum on n’offre pas de support technique et aucune garantie de la part de Microsoft ne peut être offerte.

    vendredi 23 mars 2012 13:43
  •  

    Re-Bonjour,

    On a écrit presque dans le même temps. J Merci pour avoir partagé avec nous la solution !

    Bonne journée,

    Cipri


    Suivez MSDN sur Twitter   Suivez MSDN sur Facebook


    Ciprian DUDUIALA, MSFT  
    •Nous vous prions de considérer que dans le cadre de ce forum on n’offre pas de support technique et aucune garantie de la part de Microsoft ne peut être offerte.

    vendredi 23 mars 2012 13:47
  • Merci à toi également.

    Bonne journée

    vendredi 23 mars 2012 13:51