在sqlserver中分组

时间:2018-01-15 11:40:10

标签: sql-server grouping gaps-and-islands

我的数据与下面类似。我需要根据数据的出现对状态列进行分组。

Id  Status  Value
1     K      1
2     K      3
3     K      2
4     B      2
5     B      3
6     K      6
7     J      5
8     J      2

我想要数据如下

Status  Value
K       6
B       5
K       6
J       7

我需要值列的累积和。在状态列中,如果数据连续相同,那么我需要添加值列。我不能申请分组。在给出的例子中,K重复两次,因为它们不是连续的。

我已尝试过以下查询,但它无法按要求运行。

select Status,
       (select sum(value)
        from table t2
        where 
          t2.Status = t.Status and
           t2.SNO <= t.SNO
       ) as total

from table t;

请帮助!!

1 个答案:

答案 0 :(得分:7)

这是一个差距和离岛问题

我通过使用递增ID并将其与ROW_NUMBER窗口函数相结合来解决这些问题

--Using a CTE just to replicate the sample data
;WITH cteX (Id,Status,Value)
AS(
    SELECT 1,'K', 1 UNION ALL
    SELECT 2,'K', 3 UNION ALL
    SELECT 3,'K', 2 UNION ALL
    SELECT 4,'B', 2 UNION ALL
    SELECT 5,'B', 3 UNION ALL
    SELECT 6,'K', 6 UNION ALL
    SELECT 7,'J', 5 UNION ALL
    SELECT 8,'J', 2
)
SELECT
      Grp = Id - ROW_NUMBER()OVER( PARTITION BY X.Status ORDER BY X.Id) 
    , X.Id
    , X.Status
    , X.Value
FROM 
    cteX X
ORDER BY
    X.Id

这给出了这个结果集,请注意Grp列

Grp     Id      Status  Value
------- ------- ------- -------
0       1       K       1
0       2       K       3
0       3       K       2
3       4       B       2
3       5       B       3
2       6       K       6
6       7       J       5
6       8       J       2

然后与CTE或派生表结合,您可以获得预期的输出

--Using a CTE just to replicate the sample data
;WITH cteX (Id,Status,Value)
AS(
    SELECT 1,'K', 1 UNION ALL
    SELECT 2,'K', 3 UNION ALL
    SELECT 3,'K', 2 UNION ALL
    SELECT 4,'B', 2 UNION ALL
    SELECT 5,'B', 3 UNION ALL
    SELECT 6,'K', 6 UNION ALL
    SELECT 7,'J', 5 UNION ALL
    SELECT 8,'J', 2
)
SELECT Y.Status
     , Value = SUM(Y.Value)
FROM
(
    SELECT TOP 100 PERCENT
          Grp = Id - ROW_NUMBER()OVER( PARTITION BY X.Status ORDER BY X.Id) 
        , X.Id
        , X.Status
        , X.Value
    FROM 
        cteX X
    ORDER BY
        X.Id
) Y
GROUP BY
    Y.Grp, Y.Status

输出

Status  Value
------- -------
B       5
J       7
K       6
K       6

更新问题包括&#34;保留订单&#34;溶液

只需加入Order by MIN(Id)

即可
--Using a CTE just to replicate the sample data
;WITH cteX (Id,Status,Value)
AS(
    SELECT 1,'K', 1 UNION ALL
    SELECT 2,'K', 3 UNION ALL
    SELECT 3,'K', 2 UNION ALL
    SELECT 4,'B', 2 UNION ALL
    SELECT 5,'B', 3 UNION ALL
    SELECT 6,'K', 6 UNION ALL
    SELECT 7,'J', 5 UNION ALL
    SELECT 8,'J', 2
)
    SELECT 
         Y.[Status]
        ,[Value] = SUM(Y.[Value])
    FROM
    (
        SELECT
              Grp = Id - ROW_NUMBER()OVER( PARTITION BY X.[Status] ORDER BY X.Id) 
            , X.Id
            , X.[Status]
            , X.[Value]
        FROM 
            cteX X
    ) Y
    GROUP BY
        Y.Grp, Y.[Status]
    ORDER BY
        MIN(Y.Id) --preserve the Status Order

输出

Status  Value
------- -------
K       6
B       5
K       6
J       7