Запрос Snowflake Flatten для массива - PullRequest
0 голосов
/ 25 мая 2020

Таблица Snowflake имеет 1 столбец Variant и загружена 3 JSON записями. Записи JSON выглядят следующим образом.

{"адрес": {"Город": "Лексингтон", "Адрес1": "316 Tarrar Springs Rd", "Адрес2": null} {"адрес" : {"Город": "Хартфорд", "Адрес1": "318 Спрингс Роуд", "Адрес2": "319 Спрингс Роуд"} {"адрес": {"Город": "Эйвон", "Адрес1": "38 Springs Rd "," Address2 ": [{" txtvalue ": null}, {" txtvalue ":" Line 1 "}, {" Line1 ":" Line 1 "}]}

Если вы посмотрите на поле Address2 в JSON, первое содержит NULL, 2-ю строку и 3-й массив.

Когда я выполняю плоский запрос для Address 2, поскольку одна запись содержит массив, я получаю только 3-ю запись. . Как получить все 2 записи с разнесенным значением в одном запросе.

выберите данные: адрес: City :: string, data: address: Address1 :: string, value: txtvalue :: string from add1, lateral flatten (ввод => данные: адрес: Адрес2);

1 Ответ

1 голос
/ 26 мая 2020

Когда я выполняю плоский запрос для адреса 2, поскольку одна запись содержит массив, я получаю только третью запись

поведение по умолчанию табличной функции FLATTEN в Snowflake пропустит все столбцы, у которых нет структуры для расширения, и аргумент OUTER управляет этим поведением. Цитирование соответствующей части из ссылки на документацию выше (выделено мной):

OUTER => TRUE | FALSE

Если FALSE, любые входные строки , которые не могут быть расширены , либо потому, что к ним нельзя получить доступ в пути, либо потому, что у них нет полей или записей, являются полностью опущено из вывода .

Если TRUE, для расширений с нулевой строкой создается ровно одна строка (с NULL в столбцах KEY, INDEX и VALUE ).

По умолчанию: FALSE

Поскольку ваши данные VARIANT имеют странную форму, вам необходимо использовать условные выражения * Предикаты типа данных 1041 * и , чтобы проверить, имеет ли столбец в развернутой строке тип ARRAY, VARCHAR или что-то еще, и использовать результат для выдачи правильного значения.

Пример запроса, иллюстрирующий использование всего вышеперечисленного:

SELECT
    t.v:address.City AS city
  , t.v:address.Address1 AS address1
  , CASE
        WHEN IS_ARRAY(t.v:address.Address2) THEN f.value:txtvalue::string
        ELSE t.v:address.Address2::string
    END AS address2
FROM
    add1 t
  , LATERAL FLATTEN(INPUT => v:address.Address2, OUTER => TRUE) f;

Ps Рассмотрите возможность стандартизации входных данных при захвате или источнике, чтобы снизить сложность запроса.

Примечание: Ваш пример данных несовместим (массив объектов не имеет однородных ключей), bu Следуя вашему примеру запроса, я предположил, что все ключи объектов в массиве будут называться txtvalue.

...