如何为每一行聚合不同数量的列

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,这样您就可以清楚地看到哪些条目正在求和 - 这仅用于故障排除。您可以从查询中删除它,因为它不是真正需要的