运行 total/ID 根据 SQL 中的特定值分组

Running total/ID groups based on specific value in TSQL

我的数据看起来像 ID 和 Col1,其中 Col1 中的值 01 表示持续到下一个 01 的相关行组的开始。

示例数据:

ID  Col1    
1   01      
2   02      
3   02      
---------
4   01
5   02
6   03
7   03
----------
8   01
9   03
----------
10  01

我需要计算 GroupTotal,它提供了来自 Col1 的“01”的 运行 总数,还有 GroupID,它是一个增量 ID,在 Col 1 中的每个“01”实例时重置。行订单必须和ID一起保存。

想要的结果:

ID  Col1    GroupTotal  GroupID
1   01      1           1
2   02      1           2
3   02      1           3
----------------------------
4   01      2           1
5   02      2           2
6   03      2           3
7   03      2           4
----------------------------
8   01      3           1
9   03      3           2
----------------------------
10  01      4           1

我一直在搞乱 OVER、PARTITION BY 等,也无法破解。

谢谢

如果我没理解错的话,这就是你想要的:

CREATE TABLE #tmp
    ([ID] int, [Col1] int, [GroupTotal] int, [GroupID] int)
;

INSERT INTO #tmp
    ([ID], [Col1], [GroupTotal], [GroupID])
VALUES
    (1, 01, 1, 1),
    (2, 02, 1, 2),
    (3, 02, 1, 3),
    (4, 01, 2, 1),
    (5, 02, 2, 2),
    (6, 03, 2, 3),
    (7, 03, 2, 4),
    (8, 01, 3, 1),
    (9, 03, 3, 2),
    (10, 01, 4, 1)
;

select *, row_number() over (partition by Grp order by ID) as GrpID From (
    select ID, Col1, [GroupTotal], 
    sum(case when Col1 = '01' then 1 else 0 end) over (Order by ID) as Grp, 
    [GroupID]
from #tmp

总和处理分组大小写,当 Col1=01 时总是加 1,然后在 row_number 中用于分组。

Example

我不太确定你在追求什么,但你在分区功能的正确轨道上。下面按grouptotal计算出运行个groupid的总数。我确定这不是您想要的,但它向您展示了如何实现它。

select  *, SUM(GroupId) over (partition by grouptotal order by id)
from #tmp
order by grouptotal, id

我相信 OP 所说的是唯一可用的数据是带有 idcol1 数据的 table,并且期望的结果是当前发布的在问题中。

如果是这样,您只需要以下内容。

示例数据设置:

declare @grp_tbl table (id int, col1 int)

insert into @grp_tbl (id, col1)
values (1, 1),(2, 2),(3, 2),(4, 1),(5, 2),(6, 3),(7, 3),(8, 1),(9, 3),(10, 1)

答案:

declare @max_id int = (select max(id) from @grp_tbl)

; with grp_cnt as
    (
        --getting the range of ids that are in each group
        --and ranking them
        select gt.id
        , lead(gt.id - 1, 1, @max_id) over (order by gt.id asc) as id_max --max id in the group
        , row_number() over (order by gt.id asc) as grp_ttl
        from @grp_tbl as gt
        where 1=1
        and gt.col1 = 1
    )
--ranking the range of ids inside each group
select gt.id
, gt.col1
, gc.grp_ttl as group_total
, row_number() over (partition by gc.grp_ttl order by gt.id asc) as group_id
from @grp_tbl as gt
left join grp_cnt as gc on gt.id between gc.id and gc.id_max

最终结果:

  id    col1    group_total  group_id
    1     1       1           1
    2     2       1           2
    3     2       1           3
    4     1       2           1
    5     2       2           2
    6     3       2           3
    7     3       2           4
    8     1       3           1
    9     3       3           2
    10    1       4           1