Sql SAS:单个观测值的平均值()

Sql SAS:单个观测值的平均值(),sql,sas,Sql,Sas,我试图得到某个变量列表的模式。当模式不是唯一的时,我希望返回模式的平均值,以便获取模式的子查询(在较大的查询中)不会返回两个值。但是,当模式是唯一的时,由于某种原因,平均查询返回缺少的值 我有以下样本数据: data have; input betprice; datalines; 1.05 1.05 1.05 6 run; PROC PRINT; RUN; proc sql; select avg(betprice) from

我试图得到某个变量列表的模式。当模式不是唯一的时,我希望返回模式的平均值,以便获取模式的子查询(在较大的查询中)不会返回两个值。但是,当模式是唯一的时,由于某种原因,平均查询返回缺少的值

我有以下样本数据:

data have;
input betprice;
datalines; 
    1.05
    1.05
    1.05
    6
    run;
    PROC PRINT; RUN;

proc sql;
select avg(betprice) 
    from
    (select betprice, count(*) as count_betprice from have group by betprice) 
    having count_betprice = max(count_betprice);
quit;
如果我在betprice字段中再添加一些观察值,这样模式就不是唯一的,那么我会得到返回的平均值

data have;
input betprice;
datalines; 
    1.05
    1.05
    1.05
    6
    6
    6

run;
PROC PRINT; RUN;
如何更改此查询,以便始终返回模式或两个最频繁值的平均值


感谢您在这方面提供的帮助。

首先,请注意,您在外部查询中没有group by语句,而是使用having子句。这是不好的

以下是一个有效的解决方案:

proc sql;
    create view WORK.V_BETPRICE_FREQ as
    select betprice, count(*) as count_betprice
    from HAVE
    group by betprice
    ;

    select avg(betprice) as final_betprice
    from WORK.V_BETPRICE_FREQ
    where count_betprice = (select max(count_betprice) from WORK.V_BETPRICE_FREQ)
    ;
quit;
我在这里使用了一个视图来防止代码重复。 如果视图中的查询在CPU方面是一个非常繁重的操作,那么您可能希望用一个物理表替换它

编辑 作为反馈:我相信您在查询中遇到了困难,因为在您想要的外部查询中:
1.过滤后对所有记录执行聚合功能。
2.在过滤器中使用聚合函数。
如果存在group by语句,则无法执行第一步;如果不存在group by语句,则无法执行第二步


因此,在最终结果中,我将第一个保留在外部查询中,同时在附加子查询中执行第二个。

首先,请注意,外部查询中没有group by语句,而使用having子句。这是不好的

以下是一个有效的解决方案:

proc sql;
    create view WORK.V_BETPRICE_FREQ as
    select betprice, count(*) as count_betprice
    from HAVE
    group by betprice
    ;

    select avg(betprice) as final_betprice
    from WORK.V_BETPRICE_FREQ
    where count_betprice = (select max(count_betprice) from WORK.V_BETPRICE_FREQ)
    ;
quit;
我在这里使用了一个视图来防止代码重复。 如果视图中的查询在CPU方面是一个非常繁重的操作,那么您可能希望用一个物理表替换它

编辑 作为反馈:我相信您在查询中遇到了困难,因为在您想要的外部查询中:
1.过滤后对所有记录执行聚合功能。
2.在过滤器中使用聚合函数。
如果存在group by语句,则无法执行第一步;如果不存在group by语句,则无法执行第二步


因此,在最终结果中,我在外部查询中保留了第一个,而在另一个子查询中执行了第二个。

这相当困难,在使用SAS 12年后,我记不起有人/看到我在使用HAVING with GROUP BY,我想这会产生意想不到的结果

因此,对于单个查询,我的解决方案不是很好,因为它会进行两次分组

单一查询版本:

proc sql;
select avg(betprice) 
    from ( select
                  betprice
                , count(*) as count_betprice
                from work.have
                group by betprice) /* first summary */
    where count_betprice
                = select max(count_betprice)
        from
          (select
                  betprice
                , count(*) as count_betprice
                from work.have
                group by betprice) /* same summary here */;
quit;
使用中间表(或视图,如果需要)而不是相同的子查询来简化:

proc sql;
create table work.freq_sum
        as select
                betprice
                , count(*) as count_betprice
                from work.have
                group by betprice
;
select avg(betprice) 
    from work.freq_sum
    where count_betprice
                = select max(count_betprice) from work.freq_sum;
quit;
请注意,您可以通过PROC方法计算统计数据,如模式和中位数:

proc means data=have n mean mode median;
var betprice;
run;

这相当困难,在SAS工作了12年后,我记不起有人/看到过我在没有分组的情况下使用HAVING,我想这会产生意想不到的结果

因此,对于单个查询,我的解决方案不是很好,因为它会进行两次分组

单一查询版本:

proc sql;
select avg(betprice) 
    from ( select
                  betprice
                , count(*) as count_betprice
                from work.have
                group by betprice) /* first summary */
    where count_betprice
                = select max(count_betprice)
        from
          (select
                  betprice
                , count(*) as count_betprice
                from work.have
                group by betprice) /* same summary here */;
quit;
使用中间表(或视图,如果需要)而不是相同的子查询来简化:

proc sql;
create table work.freq_sum
        as select
                betprice
                , count(*) as count_betprice
                from work.have
                group by betprice
;
select avg(betprice) 
    from work.freq_sum
    where count_betprice
                = select max(count_betprice) from work.freq_sum;
quit;
请注意,您可以通过PROC方法计算统计数据,如模式和中位数:

proc means data=have n mean mode median;
var betprice;
run;

你在SAS,为什么不让SAS计算统计,因为这是它擅长的

ods output modes=want;
proc univariate data=have modes;
var betprice;
run;
ods output close;

proc means data=want;
var mode;
output out=final(keep=betprice) mean=betprice;
run;

这不会花费很长时间,对于其他程序员来说,您正在做的事情更加清楚,并且非常容易编写代码。如果你没有计算模式的平均值,你可以一步完成。

你在SAS,为什么不让SAS计算统计数据,因为这是它擅长的

ods output modes=want;
proc univariate data=have modes;
var betprice;
run;
ods output close;

proc means data=want;
var mode;
output out=final(keep=betprice) mean=betprice;
run;

这不会花费很长时间,对于其他程序员来说,您正在做的事情更加清楚,并且非常容易编写代码。如果您没有考虑模式的平均值,您可以一步完成。

完整的“have”表中的每一行都有时间戳、用户名、betprice和其他一些列。每个用户名有多个条目。较大的查询将提取每个用户名和玩家在第1-20次下注时的平均betprice以及一些其他统计数据。您建议的第一个单一查询版本适用于此!PROC单变量更适合于模式,因为它将返回多个模式。我还建议不要使用单查询版本(就像vasja一样),这并不是因为它有什么问题,而是第二个版本更容易阅读和维护(特别是如果您将第一部分作为视图)。编写大型复杂查询并不是良好编码实践的标志,除非您正在尝试“工作安全”。因为我正在从每行带有玩家名称、betprice、下注金额等的下注表开始工作,然后为每个玩家创建一个具有唯一行的聚合表,我没有立即看到将其拆分为一系列视图、中间数据步骤和临时表的价值。仅使用“subselects”来填充每个玩家行的列数据似乎更为节省。也许我在这方面走错了方向。只是如果代码分成两部分,一部分是视图(或临时表),这意味着它不会影响性能,那么它就更容易阅读和/或维护代码。一个100行长的大型查询或其他任何查询都比几个查询更难调试、维护和读取,即使在性能稍有下降的情况下将内容移动到临时表中。事实上,有时这会提高性能,因为SQL优化器可以在较小的查询上做出更好的决策(特别是因为数据的质量很重要)。完整的“have”表中的每一行都有一个时间戳、一个用户名、一个betprice和一些其他列。每个用户名有多个条目。较大的查询将提取每个用户名和玩家在第1-20次下注时的平均betprice以及一些其他统计数据。您建议的第一个单一查询版本适用于此!PROC单变量优于f