【问题标题】:Group following rows using only one flag仅使用一个标志对以下行进行分组
【发布时间】:2017-11-06 04:23:38
【问题描述】:

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

源表和所需结果

【问题讨论】:

  • 你想要 flag = 1 的行的平均值吗?

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


【解决方案1】:

您可以使用派生表和窗口函数来做到这一点:

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;

【讨论】:

  • 出色地使用SUM() 作为解析函数 +1
  • MS SQL 2008 R2:消息 102,级别 15,状态 1,第 9 行“订单”附近的语法不正确。
  • @MarkK 支持over 子句from 2008 所以你不应该对查询有问题。您是否正确复制了我的语法?
  • @iamdave 我很确定我已经正确复制了它。如果我删除 ORDER BY ID 并留下空括号 - 查询不会返回错误。
  • 根据this,它似乎只能在 MS SQL Server 2012 和更新版本中工作
猜你喜欢
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多