2010-02-25 10 views
2

J'ai une table en SqlServer 2008 avec les données du formulairedes sous-ensembles dans une table consolidation

UserID StartWeek EndWeek Type 
1  1   3   A 
1  4   5   A 
1  6   10  A 
1  11   13  B 
1  14   16  A 
2  1   5   A 
2  6   9   A 
2  10   16  B 

Je voudrais consolider/condenser les types adjacents de telle sorte que la table résultante ressemble à ceci.

UserID StartWeek EndWeek Type 
1  1   10  A 
1  11   13  B 
1  14   16  A 
2  1   9   A 
2  10   16  B 

Est-ce que quelqu'un a des suggestions quant à la meilleure façon d'accomplir cela? J'ai cherché à utiliser Row_number et Partition, mais je n'arrive pas à le faire exactement comme je le voudrais.

+0

@Oded: SQL Server 9 est SQL Server 2005. – Welbog

Répondre

1

Il y a probablement une façon plus propre de le faire, mais cela produit le résultat correct

DECLARE @t TABLE 
(UserId TINYINT 
,StartWeek TINYINT 
,EndWeek TINYINT 
,TYPE CHAR(1) 
) 

INSERT @t 
     SELECT 1,1,3,'A' 
UNION SELECT 1,4,5,'A' 
UNION SELECT 1,6,10,'A' 
UNION SELECT 1,11,13,'B' 
UNION SELECT 1,14,16,'A' 
UNION SELECT 2,1,5,'A' 
UNION SELECT 2,6,9,'A' 
UNION SELECT 2,10,16,'B' 

;WITH srcCTE 
AS 
(
     SELECT * 
       ,ROW_NUMBER() OVER (PARTITION BY t1.UserID, t1.Type 
            ORDER BY t1.EndWeek 
            ) AS rn 
     FROM @t AS t1 
) 
,recCTE 
AS 
(
     SELECT * 
       ,0 AS grp 
     FROM srcCTE 
     WHERE rn = 1 

     UNION ALL 

     SELECT s.UserId 
       ,s.StartWeek 
       ,s.EndWeek 
       ,s.TYPE 
       ,s.rn 
       ,CASE WHEN s.StartWeek - 1 = r.EndWeek 
        THEN r.grp 
        ELSE r.grp+ 1 
       END AS GRP 
     FROM srcCTE AS s 
     JOIN recCTE AS r 
     ON r.UserId = s.UserId 
     AND r.TYPE = s.TYPE 
     AND r.rn  = s.rn - 1 
) 
SELECT UserId 
     ,MIN(StartWeek) AS StartWeek 
     ,MAX(EndWeek) AS EndWeek 
     ,TYPE 
FROM recCTE AS s1 
GROUP BY UserId 
     ,TYPE 
     ,grp 
+0

À la vôtre, ce n'est peut-être pas aussi élégant que l'autre solution, mais il sera plus facile à comprendre, à la fois pour moi-même et pour mes autres coéquipiers. – Stark

1

en utilisant également un CTE, mais d'une manière légèrement différente

DECLARE @Consolidate TABLE (
    UserID INTEGER, StartWeek INTEGER, 
    EndWeek INTEGER, Type CHAR(1)) 

INSERT INTO @Consolidate VALUES (1, 1, 3, 'A') 
INSERT INTO @Consolidate VALUES (1, 4, 5, 'A') 
INSERT INTO @Consolidate VALUES (1, 6, 10, 'A') 
INSERT INTO @Consolidate VALUES (1, 14, 16, 'A') 
INSERT INTO @Consolidate VALUES (1, 11, 13, 'B') 
INSERT INTO @Consolidate VALUES (2, 1, 5, 'A') 
INSERT INTO @Consolidate VALUES (2, 6, 9, 'A') 
INSERT INTO @Consolidate VALUES (2, 10, 16, 'B') 

;WITH ConsolidateCTE AS 
(
    SELECT UserID, StartWeek, EndWeek, Type 
    FROM @Consolidate 
    UNION ALL 
    SELECT cte.UserID, cte.StartWeek, c.EndWeek, c.Type 
    FROM ConsolidateCTE cte 
      INNER JOIN @Consolidate c ON 
      c.UserID = cte.UserID 
      AND c.StartWeek = cte.EndWeek + 1 
      AND c.Type = cte.Type 
) 
SELECT UserID, [StartWeek] = MIN(Startweek), EndWeek, Type 
FROM (
      SELECT UserID, Startweek, [EndWeek] = MAX(EndWeek), Type 
      FROM ConsolidateCTE 
      GROUP BY UserID, StartWeek, Type 
     ) c 
GROUP BY UserID, EndWeek, Type 
ORDER BY 1, 2, 3 
Questions connexes