FLATTEN
FLATTEN BY
Преобразует строки исходной таблицы с помощью вертикального разворачивания контейнеров переменной длины (списков или словарей).
Например:
- 
Исходная таблица: [a, b, c] 1 [d] 2 [] 3 
- 
Таблица после вызова FLATTEN BYк левому столбцу:a 1 b 1 c 1 d 2 
В таблицах YDB не поддерживаются контейнерные типы, поэтому функция FLATTEN BY может применяться только над переменными табличных типов, создаваемых в рамках YQL запроса.
Пример
$sample = AsList(
    AsStruct(AsList('a','b','c') AS value, CAST(1 AS Uint32) AS id),
    AsStruct(AsList('d') AS value, CAST(2 AS Uint32) AS id),
    AsStruct(AsList() AS value, CAST(3 AS Uint32) AS id)
);
SELECT value, id FROM as_table($sample) FLATTEN BY (value);
Такое преобразование может быть удобным в следующих случаях:
- Когда по ячейкам из столбца-контейнера необходимо вывести статистику (например, через GROUP BY).
- Когда в ячейках столбца-контейнера хранятся идентификаторы из другой таблицы, которую нужно присоединить с помощью JOIN.
Синтаксис
- FLATTEN BYуказывается после- FROM, но перед- GROUP BY, если- GROUP BYприсутствует в запросе.
- Тип столбца-результата зависит от типа исходного столбца:
| Тип контейнера | Тип результата | Комментарий | 
|---|---|---|
| List<X> | X | Тип ячейки списка | 
| Dict<X,Y> | Tuple<X,Y> | Кортеж из двух элементов с парами «ключ—значение» | 
| Optional<X> | X | Результат практически эквивалентен конструкции WHERE foo IS NOT NULL, но тип колонкиfooбудет изменен наX | 
- По умолчанию столбец с результатом заменяет исходный. Используйте FLATTEN BY foo AS barдля сохранения исходного контейнера. В результате исходный контейнер останется доступным вfoo, а построенный — вbar.
- Чтобы построить декартово произведение нескольких столбцов-контейнеров, используйте конструкцию FLATTEN BY (a, b, c). Скобки обязательны, чтобы избежать конфликтов в грамматике.
- В FLATTEN BYможно использовать только имена столбцов из входной таблицы. Чтобы применитьFLATTEN BYк результату вычисления, используйте подзапрос.
- В FLATTEN BYможно использовать не только столбцы, но и произвольные именованные выражения (в отличие от столбцовASобязательно). Из-за грамматических неоднозначностей выражения послеFLATTEN BYдолжны быть заключены в скобки:... FLATTEN BY (ListSkip(col, 1) AS col) ...
- Если в исходном столбце были вложенные контейнеры, например List<Dict<X,Y>>,FLATTEN BYразвернет только внешний уровень. Чтобы полностью развернуть вложенные контейнеры, используйте подзапрос.
Примечание
FLATTEN BY интерпретирует опциональные типы данных как списки длины 0 или 1. Строки таблицы с NULL пропускаются, и тип столбца меняется на аналогичный неопциональный.
FLATTEN BY делает только одно преобразование за раз, поэтому на опциональных контейнерах, например, Optional<List<String>> следует использовать FLATTEN LIST BY или FLATTEN OPTIONAL BY.
Уточнение типа контейнера
Чтобы уточнить тип контейнера, по которому необходимо произвести преобразование, можно использовать:
- 
FLATTEN LIST BYДля Optional<List<T>>операцияFLATTEN LIST BYбудет разворачивать список, интерпретируяNULL-значение как пустой список.
- 
FLATTEN DICT BYДля Optional<Dict<T>>операцияFLATTEN DICT BYбудет разворачивать словарь, интерпретируяNULL-значение как пустой словарь.
- 
FLATTEN OPTIONAL BYЧтобы фильтровать NULL-значения без размножения, необходимо уточнить операцию доFLATTEN OPTIONAL BY.
Примеры
SELECT
  t.item.0 AS key,
  t.item.1 AS value,
  t.dict_column AS original_dict,
  t.other_column AS other
FROM my_table AS t
FLATTEN DICT BY dict_column AS item;
SELECT * FROM (
    SELECT
        AsList(1, 2, 3) AS a,
        AsList("x", "y", "z") AS b
) FLATTEN LIST BY (a, b);
SELECT * FROM (
    SELECT
        "1;2;3" AS a,
        AsList("x", "y", "z") AS b
) FLATTEN LIST BY (String::SplitToList(a, ";") as a, b);
Аналоги FLATTEN BY для других СУБД
- PostgreSQL: unnest;
- Hive: LATERAL VIEW;
- MongoDB: unwind;
- Google BigQuery: FLATTEN;
- ClickHouse: ARRAY JOIN / arrayJoin;
FLATTEN COLUMNS
Преобразует таблицу, в которой все столбцы должны являться структурами, в таблицу со столбцами, соответствующими каждому элементу каждой структуры из исходных столбцов.
Имена исходных столбцов-структур не используются и не возвращаются в результате. Имена элементов структур не должны повторяться в исходных столбцах.
Пример
SELECT x, y, z
FROM (
  SELECT
    AsStruct(
        1 AS x,
        "foo" AS y),
    AsStruct(
        false AS z)
) FLATTEN COLUMNS;