我的架构类似于下面的
|- name
+- cars
| |- tesla integer
| |- ferrari integer
假设每条记录都指定了汽车的订单,每个订单都指定了订购的不同汽车的数量。
现在我想查询表格,以便得到所有不同车型的总和。
所以我想要像SELECT SUM(cars.*) from table_name
这样的东西,因为我不知道汽车可能拥有的所有可能的嵌套字段。
每次添加新的汽车模型时都会动态生成模式,因此在我的查询中,我不可能指定所有字段名称,因为我不会拥有它们。
示例数据 -
name | cars.tesla | cars.ferrari
vendor1 | 12 | 10
vendor1 | 5 | 5
vendor2 | 4 | 3
vendor1的期望输出 -
name | total_tesla | total_ferrari
vendor1 | 17 | 15
所以,我想选择嵌套在特定记录下的所有字段的总和。我有办法做到吗?
答案 0 :(得分:2)
以下是BigQuery Standard SQL
#standardSQL
SELECT name, SUM(SAFE_CAST(SPLIT(kv, ':')[OFFSET(1)] AS INT64)) total
FROM `project.dataset.table` t,
UNNEST(SPLIT(REGEXP_REPLACE(JSON_EXTRACT(TO_JSON_STRING(t), '$.cars'), r'^{|}$', ''))) kv
GROUP BY name
您可以使用以下虚拟数据进行上述测试/播放
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'a' name, STRUCT<tesla INT64, ferrari INT64>(1, 2) cars UNION ALL
SELECT 'b', STRUCT(3,4)
)
SELECT name, SUM(SAFE_CAST(SPLIT(kv, ':')[OFFSET(1)] AS INT64)) total
FROM `project.dataset.table` t,
UNNEST(SPLIT(REGEXP_REPLACE(JSON_EXTRACT(TO_JSON_STRING(t), '$.cars'), r'^{|}$', ''))) kv
GROUP BY name
结果是
name total
a 3
b 7
以下是上述简化/重构版本:
#standardSQL
SELECT name,
(
SELECT SUM(SAFE_CAST(SPLIT(kv, ':')[OFFSET(1)] AS INT64))
FROM UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(cars), r'^{|}$', ''))) kv
) total
FROM `project.dataset.table`
最后是“最终”版本:
#standardSQL
CREATE TEMP FUNCTION SUM_NESTED(root STRING) AS (
(SELECT SUM(SAFE_CAST(SPLIT(kv, ':')[OFFSET(1)] AS INT64))
FROM UNNEST(SPLIT(REGEXP_REPLACE(root, r'^{|}$', ''))) kv)
);
SELECT name, SUM_NESTED(TO_JSON_STRING(cars)) total
FROM `project.dataset.table`
更新以解决已编辑的问题
下面应该给你方向 - 它会给你扁平的结果(you should search this site then for how to pivot it - there are plenty of questions/answers on that topic here
)
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'vendor1' name, STRUCT<tesla INT64, ferrari INT64>(12, 10) cars UNION ALL
SELECT 'vendor1', STRUCT(5, 5) UNION ALL
SELECT 'vendor2', STRUCT(4,3) UNION ALL
SELECT 'vendor2', STRUCT(1,NULL)
)
SELECT
name,
REPLACE(SPLIT(kv, ':')[OFFSET(0)], '"', '') car,
SUM(SAFE_CAST(SPLIT(kv, ':')[OFFSET(1)] AS INT64)) total
FROM `project.dataset.table`,
UNNEST(SPLIT(REGEXP_REPLACE(TO_JSON_STRING(cars), r'^{|}$', ''))) kv
GROUP BY name, car
-- ORDER BY name, car
结果是
name car total
vendor1 ferrari 15
vendor1 tesla 17
vendor2 ferrari 3
vendor2 tesla 5