多个 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]而不是[]