2017-09-15 8 views
1

을 하위 쿼리 횡 방향 : 여기 눈송이 JSON 내가 눈송이에 다음 한

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

쿼리 I입니다 :

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을 바탕으로,이처럼 보이는 테이블에 다음을 설정하는 희망 시도했다; 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; 

정확히 여기에 오류가 있습니까? 이 변환을 수행하는 더 좋은 방법이 있습니까?

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

차라리 하위 쿼리보다는 조인을 필터링 할 것, 그래서 나는 아직도 다른 답변을보고에 관심이 있어요 :

답변

0

주 - 솔루션은 실제 조인을 수행하지 않습니다. 플랫 튼은 "스트리밍"연산이며, 입력을 "폭발"한 다음 원하는 행을 선택합니다. 데이터에 2 개의 속성 만있는 경우 합리적으로 빨라야합니다. 그러나 그렇지 않은 경우 불필요한 데이터 폭발이 발생할 수 있습니다 (예 : 1000 개의 속성이있는 경우).

가장 빠른 솔루션은 데이터가 정확하게 구성되는 방법과 입력에 대해 가정 할 수있는 방법에 따라 다릅니다. 당신이 'A'와 'B'가 순서대로 항상 알고 예를 들어, 당신은 분명 당신이 custom_vars 항상 두 요소는 것을 알고 있지만, 순서를 알 수없는 경우

select 
    id as db_id, 
    c:id, 
    c:custom_vars[0].value, 
    c:custom_vars[1].value 
from json_tmp; 

을 사용할 수 있습니다, 당신은 할 수 예를 들어 custom_vars의 크기를 알 수없는 경우

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 반복과 (없는 경우 또는 예를 들어, null 또는 <empty_string>) 발견 key에 대한 value을 반환 extract_key(custom_vars, key) 같은 자바 스크립트 함수를 만들 수 있습니다.

희망이 도움이됩니다. 그렇지 않은 경우 문제 (데이터 등)에 대해 자세히 설명해주십시오.

+0

이것은 매우 도움이됩니다. 저는 UDF를 자바 스크립트로 작성할 수 있다는 것을 알지 못했습니다. 나는 그것이 나를위한 최선의 해결책이라고 생각한다. 배열에는 5 개의 맞춤 변수가 있습니다. – jsharp

+0

다음과 같은 UDF를 사용하는 경우 :'var obj = {}; customData.forEach ((item) => {obj [item.key] = item.value;}); obj를 반환; ', IMMUTABLE (문서에 따르면 memoization이 보장되지 않는) 이외의 방법이 있습니까? 한 번만 호출되도록하려면 어떻게해야합니까? 'select db_id as id, c : id, custom_vars : a, custom_vars : b' – jsharp

+0

시스템은 일반적으로 일반적인 서브 표현식을 최적화 할만큼 똑똑하기 때문에'select my_func (C) : , my_func (C) : b 한 번만 호출하면됩니다. –

0

다음 쿼리는 작동하는 것 같다.