多个 ARRAY_AGG 是不是为所有这些保留相同的顺序?

Posted

技术标签:

【中文标题】多个 ARRAY_AGG 是不是为所有这些保留相同的顺序?【英文标题】:Does multiple ARRAY_AGG retain the same order for all of them?多个 ARRAY_AGG 是否为所有这些保留相同的顺序? 【发布时间】:2021-12-18 12:28:36 【问题描述】:

我一直擅长使用嵌套和重复字段(即数组和结构)来有效地建模数据,并帮助我的最终用户理解数据之间的关系,而无需他们进行“JOIN Wild Hunt”。

每当我需要在一个实体中建模多个字段时,作为最佳实践,我一直在使用 AoS(多个结构的数组),例如 ARRAY_AGG(STRUCT(...))ARRAY_AGG(SELECT AS STRUCT ...),并使用它为每个字段保留原始位置顺序结构中的值。

出于好奇,SoA 中的顺序如何 - 多个数组的结构,或者只是多个 ARRAY_AGG?

例如,让我们想象一个使用SELECT x, ARRAY_AGG(key) AS key, ARRAY_AGG(value) as value FROM ... 建模的键值对(不是NULLs)。 Google 表示 (Working with arrays) 对于单个数组“ARRAY_AGG() 返回的数组的顺序是任意的,因为无法保证函数连接值的顺序”。但是,我在同一步骤中使用真实数据和复杂子查询对多个 ARRAY_AGG 进行的每一次测试似乎都为我提供了键值对中预期的确切位置关系!那是巧合吗?或者在同一步骤中使用多个ARRAY_AGG 可以让我确定保持这种关系?

注意事项:

请忽略这样做,如果数组列有NULL值,则会报错; 如果我决定IGNORE NULLS,我将失去数组位置关系。

【问题讨论】:

具有相同顺序(甚至可能一致)的所有内容仍然是任意顺序,这只是意味着没有任何保证,您不应该依赖它,因为它可能会在 BigQuery 版本之间发生变化,或数据集的大小,或任意其他因素。 【参考方案1】:

承认答案是,如果有人对这种类型的数据进行建模决定使用数组结构,则无法保证会保留相同的顺序(正如 Mark 评论和 BigQuery 文档中所写)对于更简单建模的结构体数组,还是有办法保证顺序的。

如果你有一个你想要聚合的值的键,使用ORDER BY 作为ARRAY_AGG() 的参数就可以了。请记住,如果您正在聚合两个表来建模一个数组结构,并且左侧的表具有与右侧不匹配的连接键,则需要使用 IGNORE NULLS 条件!

下面是 BigQuery 标准 SQL 的一些代码,可帮助您测试/使用它:

#standardSQL
WITH entities AS (
    SELECT 1    AS entity_id
    UNION ALL SELECT 2
    UNION ALL SELECT 3
),
properties AS (
    SELECT 
        1       AS entity_id, 
        10      AS property_id,
        "a"     AS type, 
        TRUE    AS flag,
        "DONE"  AS status
    UNION ALL SELECT 1, 11, "b", TRUE , "TO DO"
    UNION ALL SELECT 1, 12, "c", FALSE, "DOING"
    UNION ALL SELECT 2, 20, "a", TRUE , "TO DO"
    UNION ALL SELECT 2, 21, "b", FALSE, "DONE"
)
SELECT 
    entity_id, 
    STRUCT(
        ARRAY_AGG(type   IGNORE NULLS ORDER BY property_id)  AS type, 
        ARRAY_AGG(flag   IGNORE NULLS ORDER BY property_id)  AS flag,
        ARRAY_AGG(status IGNORE NULLS ORDER BY property_id)  AS status
    )                                                           AS properties 
FROM entities 
LEFT JOIN properties USING(entity_id) 
GROUP BY entity_id

Query Results

【讨论】:

以上是关于多个 ARRAY_AGG 是不是为所有这些保留相同的顺序?的主要内容,如果未能解决你的问题,请参考以下文章

Postgres为连接表的array_agg返回[null]而不是[]

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

单个查询中的多个 array_agg() 调用

bigquery中的多个array_agg

Knex:如何在 knex 中的有子句中编写 ARRAY_AGG?

PostgreSql 聚合函数string_agg与array_agg