[英]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.