Тип данных Struct
Понятийно, колонка STRUCT содержит упорядоченный список колонок, называемых «элементами». Элементы ссылаются по имени, используя строки. В этом документе эти имена элементов называются ключами. У каждой строки в колонке STRUCT должны быть одинаковые ключи. Имена элементов структуры являются частью схемы. У каждой строки в колонке STRUCT должна быть одинаковая структура. Имена элементов структуры нечувствительны к регистру.
STRUCT обычно используются для вложенности нескольких колонок в одну колонку, и вложенная колонка может быть любого типа, включая другие STRUCT и LIST.
STRUCT похожи на тип ROW в PostgreSQL. Основное отличие состоит в том, что STRUCT DuckDB требуют одинаковых ключей в каждой строке колонки STRUCT. Это позволяет DuckDB значительно повысить производительность, полностью используя свой векторный движок выполнения, а также обеспечивает согласованность типов для повышения корректности. DuckDB включает функцию row, как специальный способ создания STRUCT, но не имеет типа данных ROW. См. пример ниже и STRUCT документацию по функциям для получения подробностей.
STRUCT имеют фиксированную схему. Изменить схему STRUCT с помощью операций UPDATE невозможно.
См. обзор типов данных для сравнения вложенных типов данных.
Создание структур
Структуры можно создавать, используя функцию struct_pack(name := expr, ...), эквивалентную нотации массивов {'name': expr, ...}, используя переменную строки или используя функцию row.
Создайте структуру, используя функцию struct_pack. Обратите внимание на отсутствие одинарных кавычек вокруг ключей и использование оператора :=:
SELECT struct_pack(key1 := 'value1', key2 := 42) AS s;
Создайте структуру, используя нотацию массивов:
SELECT {'key1': 'value1', 'key2': 42} AS s; Создайте структуру, используя переменную строки:
SELECT d AS s FROM (SELECT 'value1' AS key1, 42 AS key2) d;
Создайте структуру целых чисел:
SELECT {'x': 1, 'y': 2, 'z': 3} AS s; Создайте структуру строк со значением NULL:
SELECT {'yes': 'duck', 'maybe': 'goose', 'huh': NULL, 'no': 'heron'} AS s; Создайте структуру с разными типами для каждого ключа:
SELECT {'key1': 'string', 'key2': 1, 'key3': 12.345} AS s; Создайте структуру структур со значениями NULL:
SELECT {
'birds': {'yes': 'duck', 'maybe': 'goose', 'huh': NULL, 'no': 'heron'},
'aliens': NULL,
'amphibians': {'yes': 'frog', 'maybe': 'salamander', 'huh': 'dragon', 'no': 'toad'}
} AS s; Добавление поля(ей)/значения(ий) в структуры
Добавьте в структуру целых чисел:
SELECT struct_insert({'a': 1, 'b': 2, 'c': 3}, d := 4) AS s; Извлечение из структур
Извлечение значения из структуры можно выполнить с помощью точечной нотации, квадратной нотации или через функции структур, такие как struct_extract.
Используйте точечную нотацию для извлечения значения по месту ключа. В следующем запросе подзапрос генерирует колонку со структурой a, которую мы затем запрашиваем с помощью a.x.
SELECT a.x FROM (SELECT {'x': 1, 'y': 2, 'z': 3} AS a); Если ключ содержит пробел, просто заключите его в двойные кавычки (").
SELECT a."x space" FROM (SELECT {'x space': 1, 'y': 2, 'z': 3} AS a); Также можно использовать квадратную нотацию. Обратите внимание, что здесь используются одинарные кавычки (') так как цель — указать определенный строковый ключ, и внутри скобок могут быть только константные выражения (никаких выражений):
SELECT a['x space'] FROM (SELECT {'x space': 1, 'y': 2, 'z': 3} AS a); Функция struct_extract также эквивалентна. Это возвращает 1:
SELECT struct_extract({'x space': 1, 'y': 2, 'z': 3}, 'x space'); STRUCT.*
Вместо извлечения одного ключа из структуры, звездочка (*) может быть использована для извлечения всех ключей из структуры в качестве отдельных колонок. Это особенно полезно, когда предыдущая операция создает структуру неизвестной формы или если запрос должен обрабатывать любые возможные ключи структуры.
Все ключи внутри структуры могут быть возвращены в виде отдельных столбцов с помощью *:
SELECT a.*
FROM (SELECT {'x': 1, 'y': 2, 'z': 3} AS a); | x | y | z |
|---|---|---|
| 1 | 2 | 3 |
Порядок операций точечной нотации
Ссылка на структуры с помощью точечной нотации может быть неоднозначной при ссылке на схемы и таблицы. В общем случае DuckDB сначала ищет колонки, а затем ключи структуры внутри колонок. DuckDB разрешает ссылки в этом порядке, используя первое совпадение:
Без точек
SELECT part1 FROM tbl;
-
part1является колонкой
Одна точка
SELECT part1.part2 FROM tbl;
-
part1является таблицей,part2является колонкой -
part1является колонкой,part2является свойством этой колонки
Две (или более) точки
SELECT part1.part2.part3 FROM tbl;
-
part1— это схема,part2— это таблица,part3— это столбец -
part1— это таблица,part2— это столбец,part3— это свойство этого столбца -
part1— это столбец,part2— это свойство этого столбца,part3— это свойство этого столбца
Любые дополнительные части (например, .part4.part5, и т. д.) всегда обрабатываются как свойства
Создание структур с функцией row
Функция row может использоваться для автоматического преобразования нескольких столбцов в один столбец со структурой. При использовании row, ключи будут пустыми строками, что позволит легко вставить их в таблицу со столбцом типа структура. Однако столбцы нельзя инициализировать с помощью функции row, они должны быть явно указаны. Например, вставка значений в столбец со структурой с помощью функции row:
CREATE TABLE t1 (s STRUCT(v VARCHAR, i INTEGER));
INSERT INTO t1 VALUES (row('a', 42));
SELECT * FROM t1; Таблица будет содержать одну запись:
{'v': a, 'i': 42} Следующее производит тот же результат, что и выше:
CREATE TABLE t1 AS (
SELECT row('a', 42)::STRUCT(v VARCHAR, i INTEGER)
); Инициализация столбца со структурой с помощью функции row завершится ошибкой:
CREATE TABLE t2 AS SELECT row('a'); Invalid Input Error: A table cannot be created from an unnamed struct
При приведении структур типов, имена полей должны совпадать. Поэтому следующее запросы приведет к ошибке:
SELECT a::STRUCT(y INTEGER) AS b
FROM
(SELECT {'x': 42} AS a); Mismatch Type Error: Type STRUCT(x INTEGER) does not match with STRUCT(y INTEGER). Cannot cast STRUCTs - element "x" in source struct was not found in target struct
Обходным путём является использование struct_pack вместо этого:
SELECT struct_pack(y := a.x) AS b
FROM
(SELECT {'x': 42} AS a); Функция row может быть использована для возврата безымянных структур. Например:
SELECT row(x, x + 1, y) FROM (SELECT 1 AS x, 'a' AS y) AS s;
Это производит (1, 2, a).
Если используется несколько выражений при создании структуры, функция row необязательна. Следующий запрос возвращает тот же результат, что и предыдущий:
SELECT (x, x + 1, y) AS s FROM (SELECT 1 AS x, 'a' AS y);
Сравнение и сортировка
Тип STRUCT можно сравнивать, используя все операторы сравнения. Эти сравнения могут использоваться в логических выражениях, таких как WHERE и HAVING клаузы, и возвращают BOOLEAN значения.
Для сравнений ключи STRUCT имеют фиксированный позиционный порядок слева направо. Сравнения ведут себя так же, как сравнения строк, следовательно, соответствующие ключи должны быть в идентичных позициях.
В частности, для любого сравнения STRUCT применяются следующие правила:
-
Равенство.
s1иs2равны, если все соответствующие значения равны. -
Меньше чем. Для первого индекса
iгдеs1.value[i] != s2.value[i]: Еслиs1.value[i] < s2.value[i],s1меньше чемs2.
Значения NULL сравниваются в соответствии с семантикой PostgreSQL. Для определения ничьей используются более низкие уровни вложенности.
Ниже приведены некоторые запросы, возвращающие true для сравнения.
SELECT {'k1': 2, 'k2': 3} < {'k1': 2, 'k2': 4} AS result; SELECT {'k1': 'hello'} < {'k1': 'world'} AS result; Эти запросы возвращают false.
SELECT {'k2': 4, 'k1': 3} < {'k2': 2, 'k1': 4} AS result; SELECT {'k1': [4, 3]} < {'k1': [3, 6, 7]} AS result; Эти запросы возвращают NULL.
SELECT {'k1': 2, 'k2': 3} < {'k1': 2, 'k2': NULL} AS result; Этот запрос возвращает Binder Error, потому что ключи не совпадают по позиции.
SELECT {'k1': 2, 'k2': 3} < {'k2': 2, 'k1': 4} AS result; Binder Error: Cannot compare values of type STRUCT(k1 INTEGER, k2 INTEGER) and type STRUCT(k2 INTEGER, k1 INTEGER) - an explicit cast is required
Функции
См. Функции структур.
© Copyright 2018–2024 Stichting DuckDB Foundation
Licensed under the MIT License.
https://duckdb.org/docs/sql/data_types/struct.html