将相同的行组聚合为一行

Posted

技术标签:

【中文标题】将相同的行组聚合为一行【英文标题】:Aggregate same row groups into one row 【发布时间】:2020-09-24 09:08:09 【问题描述】:

我有一张有 30 列的表格。同一行组中除两列 (CropVariety, Date) 之外的所有值都相同。我想将具有相同列值(CropVariety、Date 除外)的行组聚合为一行,将不同的列值堆叠到一个单元格中。

Exapmple:

ID      Field      Year IDFarm Farm   Type         CropVariety  Date
1222980 MU-9 - EKO 2020 219255  MU    Cover Crop   Rice         2020-04-03
1222980 MU-9 - EKO 2020 219255  MU    Cover Crop   Soy          2020-04-07
3333333 AB-9 - EKO 2020 444444  AB    Cover Crop   Lentil       2020-05-03
3333333 AB-9 - EKO 2020 444444  AB    Cover Crop   Hemp         2020-05-07


Desired output:

ID      Field      Year IDFarm Farm   Type         CropVariety  Date
1222980 MU-9 - EKO 2020 219255  MU    Cover Crop   Rice, Soy    2020-04-03, 2020-04-07
3333333 AB-9 - EKO 2020 444444  AB    Cover Crop   Lentil, Hemp 2020-05-03, 2020-05-07

我认为我应该使用 ARRAY_AGGARRAY_CONCAT_AGG 函数,但我的公式总是错误的,所以我真的不知道如何使用 is。

【问题讨论】:

【参考方案1】:

我有一个有 30 列的表格。

在 SELECT 列表和 GROUP BY 子句中输入 30 个(或者在许多实际情况下甚至更多)列名总是很痛苦,并且是拼写错误等的根源。

同一行组中除两列 (CropVariety, Date) 之外的所有值都相同。

显然,在查询中只使用这两个列名会很好

因此,以下是针对此类情况的通用解决方案(BigQuery 标准 SQL)

#standardSQL
SELECT ANY_VALUE(t).* EXCEPT(CropVariety, Date), 
  STRING_AGG(CropVariety, ', ') AS CropVariety, 
  STRING_AGG(CAST(Date AS STRING), ', ') AS Date
FROM `project.dataset.table` t
GROUP BY TO_JSON_STRING((SELECT AS STRUCT * EXCEPT(CropVariety, Date) FROM UNNEST([t])))

正如您在此处看到的 - 仅显式使用 CropVarietyDate 列名 - 其余部分由代码处理

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

Row ID          Field           Year    CropVariety     Date     
1   1222980     MU-9 - EKO      2020    Rice, Soy       2020-04-03, 2020-04-07   
2   3333333     AB-9 - EKO      2020    Lentil, Hemp    2020-05-03, 2020-05-07  

【讨论】:

非常感谢您提供这个智能解决方案!完美运行!【参考方案2】:

更新:查看 Mikhail 的答案以获取批量指定列的语法。

======= 你说 ARRAY_AGG 但你的预期结果看起来像一个字符串。您可以使用下面的查询(如果您确实需要数组,请将 STRING_AGG() 替换为 ARRAY_AGG())

WITH data AS (
    SELECT 1222980 ID, 'MU-9 - EKO' Field, 2020 Year, "Rice" CropVariety, DATE('2020-04-03') Date
    UNION ALL
    SELECT 1222980 ID, 'MU-9 - EKO' Field, 2020 Year, "Soy" CropVariety, DATE('2020-04-07') Date
    UNION ALL
    SELECT 3333333 ID, 'AB-9 - EKO' Field, 2020 Year, "Lentil" CropVariety, DATE('2020-05-03') Date
    UNION ALL
    SELECT 3333333 ID, 'AB-9 - EKO' Field, 2020 Year, "Hemp" CropVariety, DATE('2020-05-07') Date
)
SELECT ID, Field, Year, string_agg(CropVariety, ', '), string_agg(CAST(Date AS STRING), ', ')
FROM data
GROUP BY 1,2,3

输出:

+---------+------------+------+--------------+------------------------+
|   ID    |   Field    | Year |     f0_      |          f1_           |
+---------+------------+------+--------------+------------------------+
| 1222980 | MU-9 - EKO | 2020 | Rice, Soy    | 2020-04-03, 2020-04-07 |
| 3333333 | AB-9 - EKO | 2020 | Lentil, Hemp | 2020-05-03, 2020-05-07 |
+---------+------------+------+--------------+------------------------+

【讨论】:

以上是关于将相同的行组聚合为一行的主要内容,如果未能解决你的问题,请参考以下文章

如何在pandas中将多个相同类别的行组合成一个?

查找具有已定义结束的连续相同值的行组 (SQL Redshift)

如何使用熊猫将多行组合成具有多条件的行[关闭]

将具有相同 id 的行合并为一行,保留所有数据

聚合具有两个或多个具有相同值的列的行

识别非常接近的行组