2017-09-29 3 views
-2

Je l'ensemble de données suivantes:Merging périodes d'absence

;with Data AS 
(
select '001' AS PERSONNUM,'2017-09-18 00:00:00.000' AS START,'2017-09-21 00:00:00.000' AS [END] 
UNION 
select '001','2017-09-22 00:00:00.000' AS START,'2017-09-22 00:00:00.000' AS [END] 
UNION 
select '002','2017-09-18 00:00:00.000' AS START,'2017-09-20 00:00:00.000' AS [END] 
UNION 
select '002','2017-09-22 00:00:00.000' AS START,'2017-09-22 00:00:00.000' AS [END] 
) 
select * from Data 

enter image description here

je dois fusionner les dossiers si la différence de jours entre la colonne START de la ligne suivante et la colonne END de la colonne précédente pour certains employés (PERSONNUM) est égal à 1. Dans mes exemples, pour les enregistrements «001» de personne, il faut fusionner, pour la personne «002», pas de changement.

Ainsi, les résultats attendus seront les suivants:

enter image description here

Merci à l'avance!

+1

double possible de [Combiner des plages de dates consécutives] (https://stackoverflow.com/questions/15783315/combine-consecutive-dates-ranges) –

+0

@TabAlleman - Même problème mais il existe de meilleures solutions, plus efficaces, que celle qui a été marquée comme réponse. C'est un meilleur endroit pour commencer ... http://sqlmag.com/sql-server/new-solution-packing-intervals-problem –

+0

@ JasonA.Long Ensuite, je suggère, si vous le souhaitez, de créer une réponse élaborant à ce sujet dans la question liée! Cette question semble vraiment être un doublon, donc sera probablement fermé comme un. Vos idées sont intéressantes pour tout le monde, mais leur place est dans l'autre question. – Pac0

Répondre

2

Quelque chose le long de ces lignes ... Fondamentalement prises directement à partir Itzik Ben-Gan's New Solution to the Packing Intervals Problem

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData; 

CREATE TABLE #TestData (
    PersonId CHAR(3), 
    BegDT DATETIME, 
    EndDT DATETIME 
    ); 
INSERT #TestData(PersonId, BegDT, EndDT) VALUES 
    (1, '20151231 08:00:00', '20151231 08:30:00'), 
    (1, '20151231 08:30:00', '20151231 09:00:00'), 
    (1, '20151231 09:00:00', '20151231 09:30:00'), 
    (1, '20151231 10:00:00', '20151231 11:00:00'), 
    (1, '20151231 10:30:00', '20151231 12:00:00'), 
    (1, '20151231 11:30:00', '20151231 12:30:00'), 
    (2, '20151231 08:00:00', '20151231 10:30:00'), 
    (2, '20151231 08:30:00', '20151231 10:00:00'), 
    (2, '20151231 09:00:00', '20151231 09:30:00'), 
    (2, '20151231 11:00:00', '20151231 11:30:00'), 
    (2, '20151231 11:32:00', '20151231 12:00:00'), 
    (2, '20151231 12:04:00', '20151231 12:30:00'), 
    (3, '20151231 08:00:00', '20151231 09:00:00'), 
    (3, '20151231 08:00:00', '20151231 08:30:00'), 
    (3, '20151231 08:30:00', '20151231 09:00:00'), 
    (3, '20151231 09:30:00', '20151231 09:30:00'); 

WITH 
    cte_MPE AS (
     SELECT 
      td.PersonId, td.BegDT, td.EndDT, 
      MaxPrevEnd = MAX(td.EndDT) OVER (PARTITION BY td.PersonId ORDER BY td.BegDT, td.EndDT ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) 
     FROM 
      #TestData td 
     ), 
    cte_DivGroup AS (
     SELECT 
      m.PersonId, m.BegDT, m.EndDT, m.MaxPrevEnd, 
      DivGroup = SUM(x.NewBeg) OVER (PARTITION BY m.PersonId ORDER BY m.BegDT, m.EndDT ROWS UNBOUNDED PRECEDING) 
     FROM 
      cte_MPE m 
      CROSS APPLY (VALUES (IIF(m.BegDT <= m.MaxPrevEnd, NULL, 1))) x (NewBeg) 
     ) 
SELECT 
    dg.PersonId, 
    BegDT = MIN(dg.BegDT), 
    EndDT = MAX(dg.EndDT) 
FROM 
    cte_DivGroup dg 
GROUP BY 
    dg.PersonId, 
    dg.DivGroup 
ORDER BY 
    dg.PersonId; 

... Résultats

PersonId BegDT     EndDT 
-------- ----------------------- ----------------------- 
1  2015-12-31 08:00:00.000 2015-12-31 09:30:00.000 
1  2015-12-31 10:00:00.000 2015-12-31 12:30:00.000 
2  2015-12-31 08:00:00.000 2015-12-31 10:30:00.000 
2  2015-12-31 11:00:00.000 2015-12-31 11:30:00.000 
2  2015-12-31 11:32:00.000 2015-12-31 12:00:00.000 
2  2015-12-31 12:04:00.000 2015-12-31 12:30:00.000 
3  2015-12-31 08:00:00.000 2015-12-31 09:00:00.000 
3  2015-12-31 09:30:00.000 2015-12-31 09:30:00.000 
+0

Merci beaucoup, Jason. J'ai légèrement modifié l'approche ci-dessus et obtenu des résultats corrects. –

+0

De rien. Heureux de vous aider. ;) –

+1

Apprécié. Bonne journée :) –