合并表中的子集

时间:2010-02-25 14:59:40

标签: sql sql-server

我在SqlServer 2008中有一个表格,其中包含

格式的数据
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

有没有人对完成此任务的最佳方法有任何建议?我一直在寻找使用Row_number和Partition,但我无法让它完全按照我的意愿行事。

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

也使用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