繁体   English   中英

仅当 bigquery sql 中的列值不为空时,如何按条件分组并取平均值

[英]How to group by condition and average only if column value is not null in bigquery sql

嗨,我有一个显示产品类别的表格和另一个显示产品每日价格的表格。 我想获得平均不计算空值的类别的平均价格。 我如何实现这一目标? 餐桌产品示例

产品 类别
苹果 水果
水果
葡萄 水果
芹菜 蔬菜
卷心菜 蔬菜
火鸡
牛肉

另一个表格,以每日价格和 productid 作为列,以行中的价格

日期 苹果 葡萄 芹菜 卷心菜 火鸡 牛肉
2022-01-01 2 4 1 2 3 4 3
2022-01-02 2 2 2 4 3
2022-01-03 2 2 2 3

进入

日期 水果 蔬菜
2022-01-01 3 1.5 3.3
2022-01-02 2 2 3.5
2022-01-02 2 2 3

如果平均值仅适用于不为空的列,最好不要手动执行。

考虑以下使用UNPIVOT AND PIVOT的查询:

SELECT * FROM (
  SELECT date, category, price 
    FROM prices UNPIVOT (price FOR productid IN (apple, pear, grape, celery, cabbage, chicken, turkey, beef)) p
    JOIN category c ON c.product = p.productid
) PIVOT (AVG(price) FOR category IN ('fruit', 'vegetables', 'meat'))
ORDER BY date;

在此处输入图像描述

也考虑下面的方法

create temp function keys(input string) returns array<string> language js as """
  return Object.keys(JSON.parse(input));
""";
create temp function values(input string) returns array<string> language js as """
  return Object.values(JSON.parse(input));
""";
select *
from (
  select date, category, round(avg(safe_cast(price as float64)), 2) avg_price
  from prices t, unnest([struct(to_json_string(t) as json)]),
  unnest(keys(json)) product with offset
  join unnest(values(json)) price with offset using(offset)
  left join products using(product)
  where product != 'date'
  group by date, category
)
pivot (any_value(avg_price) for category IN ('fruit', 'vegetables', 'meat'))  

如果应用于您问题中的样本数据 - 输出是

在此处输入图像描述

使用上面的潜在好处是消除从产品表中获取所有列名的需要,在您的示例中为 8,但实际上很可能更多! 显然,解决此问题的另一种方法是构建动态查询并使用execute immediate运行它,您可以在 SO 上找到很多示例。
但是,假设与产品数量相比,类别数量显着减少(仅在您的示例中很少) - 我会使用这种方法,因为execute immediate有其自身的缺点......

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM