如何在按总和分区的情况下编写没有窗口函数的 proc sql?

How to write proc sql without windowfunction over partition by sum?

我刚开始学习 SAS 并意识到 proc sql 不使用 window 函数。因为我对 sql 更放心,所以我想知道如何在 proc?window 中模拟求和函数?

想要的结果

 select a.active, a.store_id, a.nbr, sum(nbr) over (partition by a.store_id)
from(select active, store_id, count(customer_id) as nbr from customer group by active, store_id) as a
;
active store_id nbr sum
0 1 8 326
1 1 318 326
0 2 7 273
1 2 266 273

例如原始数据

select active, store_id, customer_id
from customer
limit 10;
active store_id customer_id
1 1 1
1 1 2
1 2 3
1 2 4
1 1 5
1 1 6
0 1 7
1 2 8
1 1 9
1 2 10

当前结果和查询

    select a.active, a.store_id, a.nbr, sum(nbr) 
    from(select active, store_id, count(customer_id) as nbr from customer group by active, store_id) as a
    group by a.active, a.store_id, a.nbr;
active store_id nbr sum
0 1 8 8
1 1 318 318
0 2 7 7
1 2 266 266

您可以通过合并两个 sub-queries 在 proc sql 中做同样的事情:一个用于 active, store_id 的客户数量,另一个用于每个 store_id 的客户总数].

proc sql noprint;
    create table want as
        select t1.active
             , t1.store_id
             , t1.nbr
             , t2.sum
        from (select active
                   , store_id
                   , count(customer_id) as nbr
              from have 
              group by store_id, active
             ) as t1

        LEFT JOIN

             (select store_id
                   , count(customer_id) as sum
              from have
              group by store_id
             ) as t2

        ON t1.store_id = t2.store_id
    ;
quit;

如果您想以更 SASsy 的方式执行此操作,您可以 运行 proc means 并将包含您需要的所有内容的单个数据集的结果合并在一起。 proc means 将默认计算所有可能的变量组合。

proc means data=have noprint;
    class store_id active;
    ways 1 2;

    output out=want_total
        n(customer_id) = total
    ;
run;

data want;
    merge want_total(where=(_TYPE_ = 3) rename=(total = nbr) )
          want_total(where=(_TYPE_ = 2) rename=(total = sum) keep=_TYPE_ store_id total)
    ;
    by store_id;

    drop _:;
run;

或者,在 SQL 中:

proc sql;
    create table want as
        select t1.store_id
             , t1.active
             , t1.total as nbr
             , t2.total as sum
        from want_total as t1
        LEFT JOIN
             want_total as t2
        ON t1.store_id = t2.store_id
        where     t1._TYPE_ = 3
              AND t2._TYPE_ = 2
    ;
quit;

_TYPE_ 变量标识分析级别。例如,_TYPE_ = 1 仅适用于 active_TYPE_ = 2 仅适用于 store_id_TYPE_ = 3 适用于所有组合。您可以在 proc means:

的输出数据集中查看此内容
store_id    active  _TYPE_  _FREQ_  total
.           0       1        3      3
.           1       1        7      7
1           .       2        6      6
2           .       2        4      4
1           0       3        1      1
1           1       3        5      5
2           0       3        2      2
2           1       3        2      2

如果您想要更快的 high-performance 结果,请查看它的大兄弟 proc hpsummary

这就是 SAS 的酷炫之处:您可以通过 Pandas/proc python 在 PROC、SQL、DATA 步和 Python 之间跳转。您可以利用这些方法和思维过程中的每一种的独特优势来解决任意数量的数据工程和统计问题。

与某些 SQL 实现不同,当您包含既不是分组依据也不是汇总统计的变量时,SAS 很乐意 re-merge 将汇总统计返回到详细信息行。

让我们将您打印的数据转换为实际的数据集。让我们更改一个值,这样我们至少有两个 ACTIVE 值可以作为分组依据。

data have;
  input active store_id customer_id;
cards;
1 1 1
1 1 2
1 2 3
1 2 4
1 1 5
1 1 6
0 1 7
1 2 8
1 1 9
1 2 10
;

现在我们可以按 ACTIVE 和 STORE_ID 统计记录,然后通过附加商店总数来生成报告。

proc sql;
select active,store_id,nbr,sum(nbr) as store_nbr
  from (select active,store_id,count(*) as nbr 
        from have 
        group by active,store_id
       )
  group by store_id
;

结果打印输出:

  active  store_id       nbr  store_nbr
---------------------------------------
       0         1         1          6
       1         1         5          6
       1         2         4          4