我们刚开始将查询从Legacy迁移到Standard SQL,因此我们现在正在学习如何处理嵌套数据和数组.
基本上我们想要做的是从ga_sessions
表中检索以下数据:
visitor id, session id, array of skus
visitor 1, session 1, [sku_0, sku_1, (...), sku_n]
visitor 1, session 2, [skus]
Run Code Online (Sandbox Code Playgroud)
为此,我们运行了这个简单的查询:
WITH
customers_data AS(
SELECT
fullvisitorid fv,
visitid v,
ARRAY_AGG((
SELECT
prods.productsku
FROM
UNNEST(hits.product) prods)) sku
FROM
`dataset_id.ga_sessions_*`,
UNNEST(hits) hits
WHERE
1 = 1
AND _table_suffix BETWEEN FORMAT_DATE("%Y%m%d", DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
AND FORMAT_DATE("%Y%m%d", DATE_SUB(CURRENT_DATE(), INTERVAL 0 DAY))
--and (select count(productsku) from unnest(hits.product) where productsku is not null) = 1
GROUP BY
fv,
v
LIMIT
100 )
SELECT
*
FROM
customers_data
Run Code Online (Sandbox Code Playgroud)
但是我们得到了这个错误:
Error: Scalar subquery produced more than one element
Run Code Online (Sandbox Code Playgroud)
来自该hits
字段的数据如下所示:
所以当我们补充where
条款时:
and (select count(productsku) from unnest(hits.product) where productsku is not null) = 1
Run Code Online (Sandbox Code Playgroud)
它没有给出错误,但结果重复了skus,我们也丢失了更大数组内的skus.
我们的查询中是否存在一些错误,导致阵列无法使用?
如果我理解正确,我想你想要这样的东西:
WITH customers_data AS (
SELECT
fullvisitorid fv,
visitid v,
ARRAY_CONCAT_AGG(ARRAY(
SELECT productsku FROM UNNEST(hits.product))) sku
FROM
`dataset_id.ga_sessions_*`,
UNNEST(hits) hits
WHERE
_table_suffix BETWEEN
FORMAT_DATE("%Y%m%d", DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
AND FORMAT_DATE("%Y%m%d", DATE_SUB(CURRENT_DATE(), INTERVAL 0 DAY))
GROUP BY
fv,
v
LIMIT
100
)
SELECT
*
FROM
customers_data;
Run Code Online (Sandbox Code Playgroud)
这通过使用提取每行的SKU ARRAY_CONCAT_AGG
的ARRAY
子查询来保留所有SKU .如果要跨行对所有SKU进行重复数据删除,则可以替换
SELECT
*
FROM
customers_data;
Run Code Online (Sandbox Code Playgroud)
有:
SELECT *
REPLACE (ARRAY(SELECT DISTINCT s FROM UNNEST(sku) AS s) AS sku)
FROM
customers_data;
Run Code Online (Sandbox Code Playgroud)
编辑:有关更多阅读,请查看文档中的表达式子查询类型.在您的情况下,您需要一个ARRAY
子查询,因为我们的想法是ARRAY<STRUCT<...>>
在每一行中取一个并将其转换ARRAY
为字段类型,以便跨行连接数组.
ARRAY_AGG
从单个元素ARRAY_CONCAT_AGG
创建一个数组,而从数组的串联创建一个数组.它们之间的区别是类似于数组文本构造之间的差[]
和ARRAY_CONCAT
,除了_AGG
版本聚集函数.
作为一个独立的示例,您可以尝试:
WITH T AS (
SELECT ARRAY<STRUCT<x INT64, y INT64>>[(1, 10), (2, 11), (3, 12)] AS arr UNION ALL
SELECT ARRAY<STRUCT<x INT64, y INT64>>[(4, 13)] UNION ALL
SELECT ARRAY<STRUCT<x INT64, y INT64>>[(5, 14), (6, 15)]
)
SELECT ARRAY(SELECT x FROM UNNEST(arr)) AS x_array
FROM T;
Run Code Online (Sandbox Code Playgroud)
这将返回一个列x_array
,其中每个数组中的元素是x
来自每个元素的字段中的元素arr
.要连接所有数组以便结果中有一行,请使用ARRAY_CONCAT_AGG
,例如:
WITH T AS (
SELECT ARRAY<STRUCT<x INT64, y INT64>>[(1, 10), (2, 11), (3, 12)] AS arr UNION ALL
SELECT ARRAY<STRUCT<x INT64, y INT64>>[(4, 13)] UNION ALL
SELECT ARRAY<STRUCT<x INT64, y INT64>>[(5, 14), (6, 15)]
)
SELECT ARRAY_CONCAT_AGG(ARRAY(SELECT x FROM UNNEST(arr))) AS x_array
FROM T;
Run Code Online (Sandbox Code Playgroud)
对于您的其他问题,请REPLACE
接受与要替换的列配对的表达式列表.表达式可以是简单的,例如文字,或者它可以是更复杂的东西,例如ARRAY
子查询,这是我使用的.例如:
WITH T AS (
SELECT 1 AS x, 'foo' AS y, true AS z UNION ALL
SELECT 2, 'bar', false UNION ALL
SELECT 3, 'baz', true
)
SELECT * REPLACE(1 - x AS x, CAST(x AS STRING) AS y)
FROM T;
Run Code Online (Sandbox Code Playgroud)
这将替换原有x
和y
将已经从被返回的列SELECT *
与结果1 - x
和CAST(x AS STRING)
替代.
归档时间: |
|
查看次数: |
11128 次 |
最近记录: |