Postgres:使用窗口平均每月收入总和

时间:2017-03-27 21:20:03

标签: sql postgresql window-functions

我有一张产品/日期交易记录表,我想生成月平均产品类别收入的汇总表。结果如下:

┌───────────────────┬────────────────────────┐
│ product_category  │ avg_monthly_revenue    │
├───────────────────┼────────────────────────┤
│ 5000              │       65003.04         │
│ 5100              │        3301.95         │
│ 5200              │       99029.00         │
...

我正在寻找类别总数的平均值,而我天真的尝试是返回每月交易收入的平均值。

我想要的是类别每月总数,然后是那些月份的平均值。

我可以使用sum()和avg()函数的子查询聚合来完成此操作,但是我认为这可以使用Postgres SQL Window Functions进行干净的小选择来完成。奇怪的是,广泛的谷歌搜索没有产生适用的SO解决方案,所以我发布了一个问题。

以下是数据的组织方式:

=#> \dt+ customer_transactions
        Table "customer_transactions"
┌─────────────────┬────────────────┬───────────┐
│       Column    │      Type      │ Modifiers │
├─────────────────┼────────────────┼───────────┤
│ order_day       │ date           │ not null  │
│ product_id      │ text           │ not null  │
│ product_category│ text           │ not null  │
│ customer_id     │ bigint         │ not null  │
│ revenue         │ numeric(38,14) │           │
│ units           │ integer        │           │
└─────────────────┴────────────────┴───────────┘

=#> select * from customer_transactions limit 2;
order_day   product_id   product_category   customer_id revenue
24-MAR-16   A000BC2351   5000               44502       5.85
02-NOV-16   A000CB0182   5200               99833       99.50
...

这是我使用窗口函数的天真尝试:

/* this doesn't work right, it generates the monthly transaction average*/
select      distinct product_category
            , avg(revenue) over (partition by date_trunc('month', order_day), product_category)  avg_cat_month_revenue

from        customer_transactions

# result accurate but not desired monthly item-cust-category-trxn average:
┌──────────────────┬─────────────────────────┐
│ product_category │   avg_cat_month_revenue │
├──────────────────┼─────────────────────────┤
│ 5000             │       12.0143           │
│ 5000             │       12.4989           │
...
│ 5100             │       13.5472           │
│ 5100             │       13.5643           │
...

1 个答案:

答案 0 :(得分:1)

我能够在窗口函数的postgres文档的帮助下直观地解决这个问题,这些组将应用于内部聚合函数,窗口用于结果:

  

只允许在SELECT列表和查询的ORDER BY子句中使用窗口函数。在其他地方禁止使用它们,例如GROUP BY,HAVING和WHERE子句。这是因为它们在处理这些子句后在逻辑上执行。此外,窗口函数在常规聚合函数之后执行。这意味着在窗口函数的参数中包含聚合函数调用是有效的,但反之亦然。

select      distinct product_category
            , avg(sum(revenue)) over (partition by product_category)  avg_rev

from        customer_transactions

group by    date_trunc('month', order_day), product_category

聪明的部分只是在product_category上进行分区,而不是选择所有组(仅限类别),并且知道这些组仅适用于总和而不是平均值。

与excel中的手动旋转和平均相比,结果检出。

注意事项:

  • 使用nullif(revenue,0):每月总和为0,平均值为较高分母。如果您的表的事务收入为零,则在您的summand中使用nullif。
  • 你不能再添加另一个谷物平均值来获得按月分类的平均值,例如,因为选择了类别组。