如何为每一行聚合不同数量的列
How to aggregate a different number of columns for each row
我有一个 table,其数据格式如下:
一个ID对应一个年份变量,代表读数第一次达到稳定状态(实际数据是月日组合),也会有稳定期之前时间段的数据。 a
列表示在给定年份采取的措施。我想创建一个字段,该字段仅对与给定 ID 相关的那些字段求和,即对于 Id=B,我想对列 a2015-a2019
求和。我希望这是动态完成的。但是我不确定如何在不使用 case when 语句的情况下做到这一点,因为实际数据更加精细。
我最初尝试在 id、year 和 value 水平上调整 table 这样我就可以首先找到每个 id 的稳态时间段并且简单地 sum/aggregate 只有那些值 post 但转置功能在标准中不可用-sql。
你可以试试这个。
select Id, year, (isnull(a2013,0) + isnull(a2014,0) + isnull(a2015,0) + isnull(a2016,0)
+ isnull(a2017,0) + isnull(a2018,0) + isnull(a2019,0) ) as Total
from table
以下是符合您的目的的标准逻辑。 BigQuery 的语法可能不同,但您可以相应地进行调整并使用下面给定的逻辑-
SELECT A.id,A.year,SUM(A.Val)
FROM
(
SELECT id,year,[a2013] Val,2013 Yr FROM your_table
UNION ALL
SELECT id,year,[a2014],2014 FROM your_table
UNION ALL
SELECT id,year,[a2015],2015 FROM your_table
UNION ALL
SELECT id,year,[a2016],2016 FROM your_table
UNION ALL
SELECT id,year,[a2017],2017 FROM your_table
UNION ALL
SELECT id,year,[a2018],2018 FROM your_table
UNION ALL
SELECT id,year,[a2019],2019 FROM your_table
)A
WHERE A.year <= A.Yr
GROUP BY A.id,A.year
ORDER BY 1
以下适用于 BigQuery 标准 SQL 并且非常通用,希望能满足您的要求 ("how to do it without using case when statements since the actual data is even more granular.")
#standardSQL
SELECT t.*,
(
SELECT SUM(CAST(SPLIT(kv, '":')[SAFE_OFFSET(1)] AS INT64))
FROM UNNEST(REGEXP_EXTRACT_ALL(TO_JSON_STRING(t), r'"a(\d{4}":\d*)')) kv
WHERE CAST(SPLIT(kv, '":')[OFFSET(0)] AS INT64) >= year
) total,
ARRAY (
SELECT AS STRUCT SPLIT(kv, '":')[OFFSET(0)] AS key, SPLIT(kv, '":')[SAFE_OFFSET(1)] AS value
FROM UNNEST(REGEXP_EXTRACT_ALL(TO_JSON_STRING(t), r'"a(\d{4}":\d*)')) kv
WHERE CAST(SPLIT(kv, '":')[OFFSET(0)] AS INT64) >= year
) details
FROM `project.dataset.table` t
如果应用于您问题中的示例数据 - 结果是
Row id year a2013 a2014 a2015 a2016 a2017 a2018 a2019 total details.key details.value
1 a 2014 0 342 2432 34234 645 123 65 37841 2014 342
2015 2432
2016 34234
2017 645
2018 123
2019 65
2 b 2015 0 0 54 234 34 5656 3 5981 2015 54
2016 234
2017 34
2018 5656
2019 3
3 c 2016 0 0 0 765 34654 2345 654 38418 2016 765
2017 34654
2018 2345
2019 654
如您所见 - 我在此处添加了额外的列 Details
,这样您就可以清楚地看到哪些条目正在求和 - 这仅用于故障排除。您可以从查询中删除它,因为它不是真正需要的
我有一个 table,其数据格式如下:
一个ID对应一个年份变量,代表读数第一次达到稳定状态(实际数据是月日组合),也会有稳定期之前时间段的数据。 a
列表示在给定年份采取的措施。我想创建一个字段,该字段仅对与给定 ID 相关的那些字段求和,即对于 Id=B,我想对列 a2015-a2019
求和。我希望这是动态完成的。但是我不确定如何在不使用 case when 语句的情况下做到这一点,因为实际数据更加精细。
我最初尝试在 id、year 和 value 水平上调整 table 这样我就可以首先找到每个 id 的稳态时间段并且简单地 sum/aggregate 只有那些值 post 但转置功能在标准中不可用-sql。
你可以试试这个。
select Id, year, (isnull(a2013,0) + isnull(a2014,0) + isnull(a2015,0) + isnull(a2016,0)
+ isnull(a2017,0) + isnull(a2018,0) + isnull(a2019,0) ) as Total
from table
以下是符合您的目的的标准逻辑。 BigQuery 的语法可能不同,但您可以相应地进行调整并使用下面给定的逻辑-
SELECT A.id,A.year,SUM(A.Val)
FROM
(
SELECT id,year,[a2013] Val,2013 Yr FROM your_table
UNION ALL
SELECT id,year,[a2014],2014 FROM your_table
UNION ALL
SELECT id,year,[a2015],2015 FROM your_table
UNION ALL
SELECT id,year,[a2016],2016 FROM your_table
UNION ALL
SELECT id,year,[a2017],2017 FROM your_table
UNION ALL
SELECT id,year,[a2018],2018 FROM your_table
UNION ALL
SELECT id,year,[a2019],2019 FROM your_table
)A
WHERE A.year <= A.Yr
GROUP BY A.id,A.year
ORDER BY 1
以下适用于 BigQuery 标准 SQL 并且非常通用,希望能满足您的要求 ("how to do it without using case when statements since the actual data is even more granular.")
#standardSQL
SELECT t.*,
(
SELECT SUM(CAST(SPLIT(kv, '":')[SAFE_OFFSET(1)] AS INT64))
FROM UNNEST(REGEXP_EXTRACT_ALL(TO_JSON_STRING(t), r'"a(\d{4}":\d*)')) kv
WHERE CAST(SPLIT(kv, '":')[OFFSET(0)] AS INT64) >= year
) total,
ARRAY (
SELECT AS STRUCT SPLIT(kv, '":')[OFFSET(0)] AS key, SPLIT(kv, '":')[SAFE_OFFSET(1)] AS value
FROM UNNEST(REGEXP_EXTRACT_ALL(TO_JSON_STRING(t), r'"a(\d{4}":\d*)')) kv
WHERE CAST(SPLIT(kv, '":')[OFFSET(0)] AS INT64) >= year
) details
FROM `project.dataset.table` t
如果应用于您问题中的示例数据 - 结果是
Row id year a2013 a2014 a2015 a2016 a2017 a2018 a2019 total details.key details.value
1 a 2014 0 342 2432 34234 645 123 65 37841 2014 342
2015 2432
2016 34234
2017 645
2018 123
2019 65
2 b 2015 0 0 54 234 34 5656 3 5981 2015 54
2016 234
2017 34
2018 5656
2019 3
3 c 2016 0 0 0 765 34654 2345 654 38418 2016 765
2017 34654
2018 2345
2019 654
如您所见 - 我在此处添加了额外的列 Details
,这样您就可以清楚地看到哪些条目正在求和 - 这仅用于故障排除。您可以从查询中删除它,因为它不是真正需要的