【发布时间】:2017-11-06 04:23:38
【问题描述】:
我有一个带有标志列的表,它可以是真/假。 我想对行进行分组并计算列 Val 的平均值,如下图所示:
源表和所需结果
【问题讨论】:
-
你想要 flag = 1 的行的平均值吗?
标签: sql sql-server-2008 select group-by
我有一个带有标志列的表,它可以是真/假。 我想对行进行分组并计算列 Val 的平均值,如下图所示:
源表和所需结果
【问题讨论】:
标签: sql sql-server-2008 select group-by
您可以使用派生表和窗口函数来做到这一点:
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 |
+------------+------------+
这利用递归来获取您的运行分组,因此可能会有所改进,但会得到您想要的结果:
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;