2010-11-22 16 views
3

Je cherche une solution où je dois créer un ensemble d'enregistrements à partir d'un enregistrement en utilisant les données d'une autre table. La définition de la table:Division d'enregistrements dans plusieurs enregistrements à la date de début/fin

DECLARE A AS TABLE 
(
AID BIGINT NOT NULL, 
StartDate DATETIME NOT NULL, 
EndDate DATETIME 
) 

DECLARE B AS TABLE 
(
AID BIGINT NOT NULL, 
StartDate DATETIME NOT NULL, 
EndDate DATETIME NULL 
) 

L'idée est que lorsque A contient:

1 | 01-01-2010 | 01-02-2010 
2 | 01-10-2010 | 31-10-2010 

et B contient:

1 | 01-01-2010 | 15-01-2010 
2 | 15-10-2010 | 20-10-2010 

nous recevons 5 records:

1 | 01-01-2010 | 15-01-2010 
1 | 16-01-2010 | 01-02-2010 
2 | 01-10-2010 | 15-10-2010 
2 | 16-10-2010 | 20-10-2010 
2 | 21-10-2010 | 31-10-2010 

Actuellement nous faisons cela avec un curseur sur A et un inne r boucle curseur sur B, nous devons le faire dans SQLServer (TSQL ou dans le pire des cas CLR)

Des idées sur la façon d'écrire cela comme une sélection de sorte que la surcharge du curseur disparaît?

+0

Il n'est pas clair quelles sont les règles pour générer les 5 enregistrements. Expliquez ce que vous essayez d'obtenir en anglais – smirkingman

+0

dans A il y a des périodes, dans B il y a des périodes 'sub', pour chaque période dans B nous devons diviser la période dans A –

Répondre

2
DECLARE @A TABLE (AID BIGINT NOT NULL, StartDate DATETIME NOT NULL, EndDate DATETIME) 
DECLARE @B TABLE (AID BIGINT NOT NULL, StartDate DATETIME NOT NULL, EndDate DATETIME NULL) 

SET DATEFORMAT dmy 
INSERT @A VALUES (1 ,'01-01-2010','01-02-2010') 
INSERT @A VALUES (2 ,'01-10-2010','31-10-2010') 
INSERT @B VALUES (1 ,'01-01-2010','15-01-2010') 
INSERT @B VALUES (2 ,'15-10-2010','20-10-2010') 

;WITH transitions as 
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY AID ORDER BY startdate) Sequence 
    FROM (
     SELECT A.AID, A.startdate 
     FROM @a A 
     UNION 
     SELECT A.AID, B.startdate + 1 
     FROM @A A 
     INNER JOIN @b B ON B.startdate > A.startdate AND B.startdate < A.enddate 
     UNION 
     SELECT A.AID, B.enddate + 1 
     FROM @A A 
     INNER JOIN @b B ON B.enddate > A.startdate AND B.enddate < A.enddate 
     UNION 
     SELECT A.AID, A.enddate + 1 
     FROM @a A 
     WHERE A.enddate > A.startdate 
    ) T 
) 
SELECT T1.AID, T1.startdate startdate, T2.startdate - 1 enddate 
FROM transitions T1 
INNER JOIN transitions T2 ON T2.AID = T1.AID AND T2.Sequence = T1.Sequence + 1 
ORDER BY T1.AID, T1.Sequence