Sql 合并表中的子集

Sql 合并表中的子集,sql,sql-server,Sql,Sql Server,我在SQLServer2008中有一个表,其中包含以下格式的数据 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

我在SQLServer2008中有一个表,其中包含以下格式的数据

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
我希望合并/压缩相邻的类型,以便生成的表如下所示

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

有人对实现这一目标的最佳方式有什么建议吗?我一直在考虑使用行数和分区,但我不能让它完全按照我所希望的那样运行。

可能有一种更简洁的方法,但这会产生正确的结果

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

也使用CTE,但方式略有不同

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

@Oded:SQLServer9是SQLServer2005。干杯,它看起来可能没有其他解决方案那么优雅,但对我自己和我的其他队友来说,它更容易理解。