雪花json侧子查询

时间:2017-09-15 15:51:52

标签: sql json snowflake-datawarehouse

我在雪花中有以下内容:

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;

基于as the descriptor how-to states,我希望将它们变成一个如下表:

+-------+---------+-----+-----+
| db_id | json_id |  a  |  b  |
+-------+---------+-----+-----+
+-------+---------+-----+-----+
|   1   |   0x1   | foo | bar |
+-------+---------+-----+-----+

这是我试过的查询;它导致SQL编译错误:“对象'CUSTOM_VARS'不存在。”

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;

这里的错误究竟是什么?有没有更好的方法来进行这种转变?

2 个答案:

答案 0 :(得分:1)

注意 - 您的解决方案实际上并未执行任何联接 - flatten是" streaming"操作,它"爆炸"输入,然后选择它想要的行。如果数据中只有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并返回找到的value key(或者null<empty_string>,如果没有找到)。

希望这会有所帮助。如果没有,请提供有关您的问题的更多详细信息(数据等)。

答案 1 :(得分:0)

以下查询似乎有效:

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'
;

我宁愿过滤子查询而不是加入,所以我仍然有兴趣看到其他答案。