仅使用一个标志对行进行分组

时间:2017-06-05 11:42:53

标签: sql sql-server-2008 select group-by

我有一个带有Flag列的表,它可以是true / false。 我想对行进行分组并计算列Val的平均值,如下图所示:

来源表和期望结果

1 个答案:

答案 0 :(得分:3)

您可以使用派生表和窗口函数执行此操作:

declare @t table(ID int,Val decimal(10,2),Flag bit);
insert into @t values (515,5.4,0),(516,1,1),(517,0,0),(518,0,0),(519,3,0),(520,7,0),(521,8,0),(522,2,0),(523,5,0),(524,3,1),(525,1,0),(526,2,0),(527,3,0),(528,2,0),(529,8,0),(530,9,0),(531,0,0),(532,4,1),(533,0,0),(534,2,0),(535,1,0),(536,0,0),(537,0,1),(538,1,0);

with c as
(
    select ID
            ,Val
            ,Flag
            ,sum(cast(Flag as int)) over (order by ID) as rn
    from @t
)
select cast(min(ID) as nvarchar(10)) + ' to ' + cast(max(ID) as nvarchar(10)) as IDRange
    ,avg(Val) as AverageVal
from c
group by rn
order by rn;

输出:

+------------+------------+
|  IDRange   | AverageVal |
+------------+------------+
| 515 to 515 |        5.4 |
| 516 to 523 |       3.25 |
| 524 to 531 |        3.5 |
| 532 to 536 |        1.4 |
| 537 to 538 |        0.5 |
+------------+------------+

2008 R2版本的更新

这利用递归来获得正在运行的分组,因此可以改进,但会得到你想要的结果:

declare @t table(ID int,Val decimal(10,2),Flag bit);
insert into @t values (515,5.4,0),(516,1,1),(517,0,0),(518,0,0),(519,3,0),(520,7,0),(521,8,0),(522,2,0),(523,5,0),(524,3,1),(525,1,0),(526,2,0),(527,3,0),(528,2,0),(529,8,0),(530,9,0),(531,0,0),(532,4,1),(533,0,0),(534,2,0),(535,1,0),(536,0,0),(537,0,1),(538,1,0);

with t as
(
    select ID
            ,Val
            ,Flag
            ,row_number() over (order by ID) as rn
    from @t
),c as
(
    select ID
            ,Val
            ,Flag
            ,rn
            ,0 as g
    from t
    where rn = 1

    union all

    select t.ID
            ,t.Val
            ,t.Flag
            ,t.rn
            ,c.g + cast(t.Flag as int) as g
    from t
        join c
            on t.rn = c.rn+1
)
select cast(min(ID) as nvarchar(10)) + ' to ' + cast(max(ID) as nvarchar(10)) as IDRange
    ,avg(Val) as AverageVal
from c
group by g
order by g;