Следующий запрос (протестированный с Postgresql 11.1) оценивает для каждой комбинации клиент / продукт следующие элементы:
- (A) сумму продаж, которую клиент потратил на этот продукт
- (B) сумма стоимости продаж, которую клиент потратил в родительской категории этого продукта
И делит A / B, чтобы получить метрику под названием loyalty
.
select
pp.customer, pp.product, pp.category,
pp.sales_product / pc.sales_category as loyalty
from (
select
t.household_key as customer,
t.product_id as product,
p.commodity as category,
sum(t.sales_value) as sales_product
from transaction_data t
left join product p on p.product_id = t.product_id
group by t.household_key, t.product_id, p.commodity
) pp
left join (
select
t.household_key as customer,
p.commodity as category,
sum(t.sales_value) as sales_category
from transaction_data t
left join product p on p.product_id = t.product_id
group by t.household_key, p.commodity
) pc on pp.customer = pc.customer and pp.category = pc.category
;
Результаты имеют следующий вид:
customer product category loyalty
---------------------------------------------
1 tomato food 0.01
1 beef food 0.02
1 toothpaste hygiene 0.04
1 toothbrush hygiene 0.03
Мой вопрос состоит в том, чтобы вместо того, чтобы полагаться на два подзапроса, которые затем соединяются слева, было бы возможно с однимвместо этого использовать оконные функции?
Я пытался сделать что-то вроде следующего, но, очевидно, это не работает, потому что, в данном случае, column "t.sales_value" must appear in the GROUP BY clause or be used in an aggregate function
.Я не вижу, что можно сделать, чтобы это исправить.
-- does not work
select
t.household_key as customer,
t.product_id as product,
p.commodity as category,
sum(t.sales_value) as sales_product,
sum(t.sales_value) over (partition by t.household_key, p.commodity) as sales_category
from transaction_data t
left join product p on p.product_id = t.product_id
group by t.household_key, t.product_id, p.commodity;