Spec-Zone.ru › DuckDB

Тип данных 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;
  1. part1 является колонкой

Одна точка

SELECT part1.part2
FROM tbl;
  1. part1 является таблицей, part2 является колонкой
  2. part1 является колонкой, part2 является свойством этой колонки

Две (или более) точки

SELECT part1.part2.part3
FROM tbl;
  1. part1 — это схема, part2 — это таблица, part3 — это столбец
  2. part1 — это таблица, part2 — это столбец, part3 — это свойство этого столбца
  3. 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API