我的数据有几列-日期,组ID,人ID和值。每个日期有多个GroupID;每个组中有多个PersonID,并且每个组中每个人每天都有多个值。我想做的就是总结这些内容,方法是找到每一组中每个人每天的平均值和90%的百分数。因此,每行将具有唯一的Date-GroupID-PersonID标识符,然后具有与该组合关联的平均值和第90个百分位数。
这仅适用于运行平均值或仅运行百分位数,但是当我需要同时包含两者时,就会遇到问题。当前是我正在使用的代码:
select distinct GroupID
, PersonID
, Date
, avg(Value) as Value_Avg
, PERCENTILE_CONT(0.9) within group (order by Value) over (partition by GroupID, PersonID) as Value_90th
from Table
group by Date, GroupID, PersonID
它给我的错误是:“列'值'在选择列表中无效,因为它既不包含在聚合函数中也不在GROUP BY子句中。”
如果我在group by子句中添加Value,它将正确地给我第90个百分位数,但是将每个Value保留在其自己的行中,并且不对它们进行平均。如果我在Percentile函数内添加一个聚合函数,例如“按avg(Value)排序”,则它会正确地对平均值列中的值取平均值,但也只是给我百分位数列中的平均值,而不是第90个百分位数。我尝试使用其他聚合,例如min或max,这将为我提供min或max值,而不是百分位数。此外,“值”列的数据类型为十进制,互联网告诉我不应该要求汇总,但是确实如此。
所以,我有点不高兴……无论哪种方式,我尝试解决它都无法获得我想要的东西。任何帮助或见识将不胜感激!
答案 0 :(得分:0)
这里棘手的事情是,像PERCENTILE_CONT这样的分析函数不是聚合的。
所以这个
use tempdb
go
drop table if exists t
go
create table t(GroupID int, PersonId int, Date date, Value float)
insert into t(GroupID, PersonId,Date, Value)
values
(1,1,'20190829',10),
(1,1,'20190829',20),
(1,1,'20190829',30),
(1,1,'20190829',40),
(1,1,'20190829',50),
(1,2,'20190829',20),
(1,2,'20190829',40),
(1,2,'20190829',60),
(1,2,'20190829',80),
(1,2,'20190829',100)
go
select GroupID
, PersonID
, Date
, PERCENTILE_CONT(0.9) within group (order by Value) over (partition by Date, GroupID, PersonID) as Value_90th
from t
输出
GroupID PersonID Date Value_90th
----------- ----------- ---------- ----------------------
1 1 2019-08-29 46
1 1 2019-08-29 46
1 1 2019-08-29 46
1 1 2019-08-29 46
1 1 2019-08-29 46
1 2 2019-08-29 92
1 2 2019-08-29 92
1 2 2019-08-29 92
1 2 2019-08-29 92
1 2 2019-08-29 92
(10 rows affected)
因此,如果您随后要进行汇总,则可以对该列应用汇总函数或分组依据。像这样:
select GroupID
, PersonID
, Date
, avg(PERCENTILE_CONT(0.9) within group (order by Value) over (partition by Date, GroupID, PersonID)) as Value_90th
, avg(Value) as Value_Avg
from t
group by Date, GroupID, PersonID
碰巧是非法的,并失败
Msg 8120, Level 16, State 1, Line 28
Column 't.Value' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 4109, Level 15, State 1, Line 28
Windowed functions cannot be used in the context of another windowed function or aggregate.
因此,与其他分析功能一样,您可以将它们应用于子查询或CTE,如下所示:
with q as
(
select GroupID
, PersonID
, Date
, Value
, PERCENTILE_CONT(0.9) within group (order by Value) over (partition by Date, GroupID, PersonID) as Value_90th
from t
)
select Date, GroupID, PersonID, avg(value) avg_value, avg(Value_90th) Value_90th
from q
group by Date, GroupID, PersonID
哪个输出
Date GroupID PersonID avg_value Value_90th
---------- ----------- ----------- ---------------------- ----------------------
2019-08-29 1 1 30 46
2019-08-29 1 2 60 92
(2 rows affected)