雪花 json 横向子查询
snowflake json lateral subquery
我在雪花中有以下内容:
create or replace table json_tmp as select column1 as id, parse_json(column2) as c
from VALUES (1,
'{"id": "0x1",
"custom_vars": [
{ "key": "a", "value": "foo" },
{ "key": "b", "value": "bar" }
] }') v;
基于 FLATTEN
docs,我希望将这些变成 table 看起来像这样:
+-------+---------+-----+-----+
| db_id | json_id | a | b |
+-------+---------+-----+-----+
+-------+---------+-----+-----+
| 1 | 0x1 | foo | bar |
+-------+---------+-----+-----+
这是我试过的查询;它导致 SQL 编译错误:"Object 'CUSTOM_VARS' does not exist."
select json_tmp.id as dbid,
f.value:id as json_id,
a.v,
b.v
from json_tmp,
lateral flatten(input => json_tmp.c) as f,
lateral flatten(input => f.value:custom_vars) as custom_vars,
lateral (select value:value as v from custom_vars where value:key = 'a') as a,
lateral (select value:value as v from custom_vars where value:key = 'b') as b;
这里的错误到底是什么?有没有更好的方法来进行这种转换?
更新 2019 年 11 月
似乎有一个函数可以做这种事情:
select json_tmp.id as dbid,
json_tmp.c:id as json_id,
object_agg(custom_vars.value:key, custom_vars.value:value):a as a,
object_agg(custom_vars.value:key, custom_vars.value:value):b as b
from
json_tmp,
lateral flatten(input => json_tmp.c, path => 'custom_vars') custom_vars
group by json_tmp.id
原始答案 2017 年 9 月
以下查询似乎有效:
select json_tmp.id as dbid,
json_tmp.c:id as json_id,
a.value:value a,
b.value:value b
from
json_tmp,
lateral flatten(input => json_tmp.c, path => 'custom_vars') a,
lateral flatten(input => json_tmp.c, path => 'custom_vars') b
where a.value:key = 'a' and b.value:key = 'b'
;
我宁愿在子查询中过滤而不是在连接中过滤,所以我仍然有兴趣查看其他答案。
注意 - 您的解决方案实际上不执行任何连接 - 展平是一个 "streaming" 操作,它 "explodes" 输入,然后选择它想要的行。如果数据中只有 2 个属性,它应该相当快。但是,如果不这样做,可能会导致不必要的数据爆炸(例如,如果您有 1000 多个属性)。
最快的解决方案取决于您的数据的确切结构,以及您对输入的假设。例如,如果您知道 'a' 和 'b' 始终按此顺序,您显然可以使用
select
id as db_id,
c:id,
c:custom_vars[0].value,
c:custom_vars[1].value
from json_tmp;
如果您知道 custom_vars
总是 2 个元素,但顺序未知,您可以这样做,例如
select
id as db_id,
c:id,
iff(c:custom_vars[0].key = 'a', c:custom_vars[0].value, c:custom_vars[1].value),
iff(c:custom_vars[0].key = 'b', c:custom_vars[0].value, c:custom_vars[1].value)
from json_tmp;
如果 custom_vars 的大小未知,您可以创建一个像 extract_key(custom_vars, key)
这样的 JavaScript 函数来迭代 custom_vars
和 return value
用于找到 key
(或者例如 null
或 <empty_string>
,如果未找到)。
希望这对您有所帮助。如果不是,请提供有关您的问题(数据等)的更多详细信息。
我在雪花中有以下内容:
create or replace table json_tmp as select column1 as id, parse_json(column2) as c
from VALUES (1,
'{"id": "0x1",
"custom_vars": [
{ "key": "a", "value": "foo" },
{ "key": "b", "value": "bar" }
] }') v;
基于 FLATTEN
docs,我希望将这些变成 table 看起来像这样:
+-------+---------+-----+-----+
| db_id | json_id | a | b |
+-------+---------+-----+-----+
+-------+---------+-----+-----+
| 1 | 0x1 | foo | bar |
+-------+---------+-----+-----+
这是我试过的查询;它导致 SQL 编译错误:"Object 'CUSTOM_VARS' does not exist."
select json_tmp.id as dbid,
f.value:id as json_id,
a.v,
b.v
from json_tmp,
lateral flatten(input => json_tmp.c) as f,
lateral flatten(input => f.value:custom_vars) as custom_vars,
lateral (select value:value as v from custom_vars where value:key = 'a') as a,
lateral (select value:value as v from custom_vars where value:key = 'b') as b;
这里的错误到底是什么?有没有更好的方法来进行这种转换?
更新 2019 年 11 月
似乎有一个函数可以做这种事情:
select json_tmp.id as dbid,
json_tmp.c:id as json_id,
object_agg(custom_vars.value:key, custom_vars.value:value):a as a,
object_agg(custom_vars.value:key, custom_vars.value:value):b as b
from
json_tmp,
lateral flatten(input => json_tmp.c, path => 'custom_vars') custom_vars
group by json_tmp.id
原始答案 2017 年 9 月
以下查询似乎有效:
select json_tmp.id as dbid,
json_tmp.c:id as json_id,
a.value:value a,
b.value:value b
from
json_tmp,
lateral flatten(input => json_tmp.c, path => 'custom_vars') a,
lateral flatten(input => json_tmp.c, path => 'custom_vars') b
where a.value:key = 'a' and b.value:key = 'b'
;
我宁愿在子查询中过滤而不是在连接中过滤,所以我仍然有兴趣查看其他答案。
注意 - 您的解决方案实际上不执行任何连接 - 展平是一个 "streaming" 操作,它 "explodes" 输入,然后选择它想要的行。如果数据中只有 2 个属性,它应该相当快。但是,如果不这样做,可能会导致不必要的数据爆炸(例如,如果您有 1000 多个属性)。
最快的解决方案取决于您的数据的确切结构,以及您对输入的假设。例如,如果您知道 'a' 和 'b' 始终按此顺序,您显然可以使用
select
id as db_id,
c:id,
c:custom_vars[0].value,
c:custom_vars[1].value
from json_tmp;
如果您知道 custom_vars
总是 2 个元素,但顺序未知,您可以这样做,例如
select
id as db_id,
c:id,
iff(c:custom_vars[0].key = 'a', c:custom_vars[0].value, c:custom_vars[1].value),
iff(c:custom_vars[0].key = 'b', c:custom_vars[0].value, c:custom_vars[1].value)
from json_tmp;
如果 custom_vars 的大小未知,您可以创建一个像 extract_key(custom_vars, key)
这样的 JavaScript 函数来迭代 custom_vars
和 return value
用于找到 key
(或者例如 null
或 <empty_string>
,如果未找到)。
希望这对您有所帮助。如果不是,请提供有关您的问题(数据等)的更多详细信息。