平均 Postgres 中的多列

Average Multiple Columns in Postgres

我有一个包含多行的 table,每行包含以下四列:

product price_instore price_pickup price_delivery price_ship
1 .00 .50 .50 .00.
2 .00 .00 NULL NULL
3 .00 .00 .00 NULL

我想要第五列 average_price 给出产品的平均价格,但不将 NULLS 计入总价或用于除以平均值的计数。

因此产品 1 的平均价格:($13+$13.50+$14.50+$18)/4=$14.75
产品 2 的平均价格:($4+$4)/2 = $4.00
产品 3 的平均价格:($10+$10+$12)/3 = $10.67

SQL有什么办法吗?我试过如下子查询但没有成功:

(select coalesce((PRICE_INSTORE + PRICE_PICKUP + PRICE_DELIVERY + PRICE_SHIP) / 4, 
PRICE_INSTORE, PRICE_PICKUP, PRICE_DELIVERY, PRICE_SHIP) 

但如果其中任何一个为空,我只能得到一个价格

我喝醉了,所以可能有比旋转更好的方法来做到这一点,但我现在看不到它,因为房间像它一样在我周围旋转。

with j as (
  select product, to_jsonb(mytable) - 'product' as jdata
    from mytable
)
select j.product, avg(e.value::numeric) as avg_price
  from j
       cross join lateral jsonb_each(j.jdata) as e(key, value)
 where e.value is not null
 group by j.product. 

一种方法是横向连接:

select t.*, avg_price
from t cross join lateral
     (select avg(price) as avg_price
      from (values (price_instore), (price_pickup), (price_delivery), (price_ship)
           ) v(price)
     ) x
select
    *,
    (select avg(x) from unnest(array[price_instore,price_pickup,price_delivery,price_ship]) as x) as avg_price
from
   your_table;

试试这个:

   select coalesce(PRICE_INSTORE,0) + coalesce(PRICE_PICKUP,0) + coalesce(PRICE_DELIVERY,0) + coalesce(PRICE_SHIP,0)) / 4

这一个可能是最容易消化的。性能应该不会太差,除非你有一个非常大的 table 也没有索引

 with cte (product, prices) as 
  
(select product, price_instore from t union all
 select product, price_pickup from t union all
 select product, price_delivery from t union all
 select product, price_ship from t)
  
select product, avg(prices)
from cte
group by product;

您要么按原样使用输出,要么将其包装在另一个 CTE 上并使用它加入您的原始 table 以获得平均值

试试这个

  select coalesce (PRICE_INSTORE, 0 ) +  coalesce (PRICE_PICKUP, 0) + coalesce (PRICE_DELIVERY , 0) + coalesce (PRICE_SHIP , 0)  / 
 ((case when PRICE_INSTORE is null then 0 else 1 end) + (case when PRICE_PICKUP is null then 0 else 1 end) +
 (case when PRICE_DELIVERY is null then 0 else 1 end) + (case when PRICE_SHIP is null then 0 else 1 end) )
 from product