Bigquery/标准 SQL:如何使用 sum() 聚合所有列(大约 100 列)?
Posted
技术标签:
【中文标题】Bigquery/标准 SQL:如何使用 sum() 聚合所有列(大约 100 列)?【英文标题】:Bigquery/Standard SQL: How can I aggregate all columns (about 100 columns) with sum()? 【发布时间】:2018-06-11 15:21:48 【问题描述】:我正在寻找一种使用 sum() 函数聚合包含大约 100 列的 Bigquery 表的解决方案。但 Bigquery 标准 SQL 中不允许以下查询。
select sum(*)
from `dataset.Intermediate_Tables.eventCat_dummies`
group by Id
我想在 Bigquery 中进行这种聚合的原因是它能够处理大量数据。我尝试在 jupyter notebook 中进行相同的聚合,但每次都失败。这可能是因为数据量大(7.3 GiB csv 文件)。我试过的代码如下:
df_type = type_dummies.groupby('Id', sort=False).sum()
任何人都可以就如何获取这个大型数据集的聚合数据提供任何建议和/或替代方案?
使用示例输入和输出进行更新
输入数据
Id col1 col2 col3 col4
1 0 0 0 1
2 0 1 1 1
1 1 0 0 0
4 0 0 0 0
19 0 0 0 0
2 1 1 1 1
期望的输出
Id col1_sum col2_sum col3_sum col4_sum
1 1 0 0 1
2 1 2 2 2
4 0 0 0 0
19 0 0 0 0
在我的原始数据集中,有 100 列和 4000 万行。
【问题讨论】:
带有输入和预期输出的简化示例将帮助我们回答您的问题 @MikhailBerlyant 感谢您的评论。我会用一个简化的例子来更新它。 【参考方案1】:以下是 BigQuery StandardSQL 的示例
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1 id, 1 a, 2 b, 3 c UNION ALL
SELECT 1, 4, 5, 6 UNION ALL
SELECT 2, 7, 8, 9
)
SELECT id,
SUM((
SELECT SUM(CAST(SPLIT(pair, ':')[SAFE_OFFSET(1)] AS INT64))
FROM UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(t), r'[]', ''))) pair
WHERE SPLIT(pair, ':')[SAFE_OFFSET(0)] != '"id"'
)) val
FROM `project.dataset.table` t
GROUP BY id
结果为
Row id val
1 1 21
2 2 24
如您所见 - 以上不依赖于列数
此外,它假设除id
列之外的所有列都需要求和。如果您要排除更多列 - 您可以分别调整 WHERE
子句
根据提供的详细信息进行更新 所以你想对每一列求和(最初我读你的问题,好像你想通过 id 将所有列的值加在一起)
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1 id, 1 a, 2 b, 3 c UNION ALL
SELECT 1, 4, 5, 6 UNION ALL
SELECT 2, 7, 8, 9
)
SELECT id,
REPLACE(SPLIT(pair, ':')[SAFE_OFFSET(0)], '"', '') col,
SUM(CAST(SPLIT(pair, ':')[SAFE_OFFSET(1)] AS INT64)) val
FROM (
SELECT id,
ARRAY(
SELECT pair
FROM UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(t1), r'[]', ''))) pair
WHERE SPLIT(pair, ':')[SAFE_OFFSET(0)] != '"id"'
) arr
FROM `project.dataset.table` t1
) t2,
UNNEST(arr) pair
GROUP BY id, col
ORDER BY id, col
这会给你下面的结果
Row id col val
1 1 a 5
2 1 b 7
3 1 c 9
4 2 a 7
5 2 b 8
6 2 c 9
这个结果是你需要的扁平化版本,在大多数实际用例中比旋转的更有效
不过,如果您想转换此结果 - 请参阅 https://***.com/a/35808045/5221944
【讨论】:
嗨,米哈伊尔,感谢您的帮助。我正在尝试了解您的解决方案。然后我想到了几个问题。第一个问题是:当您在解决方案中使用 WITH 和 UNNEST 子句时,是否隐含涉及列名?第二个问题是 21 是如何计算的?如果我的问题太天真,我希望你不会介意。顺便说一句,我用示例输入和所需输出更新了问题。你能告诉我这个解决方案是否仍然有效吗?再次感谢。 查看答案更新。同时 - 1) WITH 仅用于模拟您的数据 - 您可以删除该部分并使用您自己的project.dataset.table
它适用于您的表和 UNNEST 中的尽可能多的列 - 正如您从脚本/查询中看到的那样- 根本不使用列名! 2) 21 是 id=1 (1+2+3+4+5+6=21) 的所有列的总和-当然这是我最初理解您的问题的方式-但是在您提供了更多详细信息之后-很清楚那不是您想要的-所以我在最初的答案中添加了更新。希望这会有所帮助:o)
感谢您分享宝贵的知识,米哈伊尔。您的解决方案和解释方法对我来说看起来很棒。我可以从中学到很多东西。尽管我没有尝试将您的想法应用于我的数据集,但我喜欢您的解决方案,并且相信它会引导我到正确的地方。我会投赞成票,希望它能帮助更多遇到类似问题的人。以上是关于Bigquery/标准 SQL:如何使用 sum() 聚合所有列(大约 100 列)?的主要内容,如果未能解决你的问题,请参考以下文章