我有一张产品/日期交易记录表,我想生成月平均产品类别收入的汇总表。结果如下:
┌───────────────────┬────────────────────────┐ │ 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 │ ...
答案 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。