Spec-Zone.ru › DuckDB

Внутреннее устройство Pivot

PIVOT

Перегруппировка реализована как комбинация переписывания SQL-запроса и специализированного PhysicalPivot оператора для повышения производительности. Каждый PIVOT реализуется как набор агрегаций в списки, а затем специализированный PhysicalPivot оператор преобразует эти списки в имена и значения столбцов. Дополнительные этапы предобработки необходимы, если столбцы, которые должны быть созданы при перегруппировке, определяются динамически (что происходит, когда IN предложение не используется).

DuckDB, как и большинство SQL-движков, требует, чтобы все имена и типы столбцов были известны в начале запроса. Для автоматического определения столбцов, которые должны быть созданы в результате PIVOT оператора, он должен быть переведён в несколько запросов. ENUM типы используются для поиска уникальных значений, которые должны стать столбцами. Каждый ENUM затем вставляется в одно из PIVOT операторов IN предложения.

После того, как IN предложения заполнены ENUM значениями, запрос снова переписывается в набор агрегаций в списки.

Например:

PIVOT cities
ON year
USING sum(population);

изначально переводится в:

CREATE TEMPORARY TYPE __pivot_enum_0_0 AS ENUM (
    SELECT DISTINCT
        year::VARCHAR
    FROM cities
    ORDER BY
        year
    );
PIVOT cities
ON year IN __pivot_enum_0_0
USING sum(population);

и, наконец, переводится в:

SELECT country, name, list(year), list(population_sum)
FROM (
    SELECT country, name, year, sum(population) AS population_sum
    FROM cities
    GROUP BY ALL
)
GROUP BY ALL;

Это даёт результат:

country name list("year") list(population_sum)
NL Amsterdam [2000, 2010, 2020] [1005, 1065, 1158]
US Seattle [2000, 2010, 2020] [564, 608, 738]
US New York City [2000, 2010, 2020] [8015, 8175, 8772]

Оператор PhysicalPivot преобразует эти списки в имена и значения столбцов, чтобы вернуть этот результат:

country name 2000 2010 2020
NL Amsterdam 1005 1065 1158
US Seattle 564 608 738
US New York City 8015 8175 8772

UNPIVOT

Внутреннее устройство

Разворот реализован полностью как переписывание в SQL-запросы. Каждый UNPIVOT реализуется как набор unnest функций, работающих со списком имён столбцов и списком значений столбцов. Если разворот происходит динамически, сначала оценивается выражение COLUMNS, чтобы вычислить список столбцов.

Например:

UNPIVOT monthly_sales
ON jan, feb, mar, apr, may, jun
INTO
    NAME month
    VALUE sales;

переводится в:

SELECT
    empid,
    dept,
    unnest(['jan', 'feb', 'mar', 'apr', 'may', 'jun']) AS month,
    unnest(["jan", "feb", "mar", "apr", "may", "jun"]) AS sales
FROM monthly_sales;

Обратите внимание на одинарные кавычки для создания списка текстовых строк для заполнения month, и двойные кавычки для извлечения значений столбцов для использования в sales. Это даёт тот же результат, что и в исходном примере:

empid dept month sales
1 electronics jan 1
1 electronics feb 2
1 electronics mar 3
1 electronics apr 4
1 electronics may 5
1 electronics jun 6
2 clothes jan 10
2 clothes feb 20
2 clothes mar 30
2 clothes apr 40
2 clothes may 50
2 clothes jun 60
3 cars jan 100
3 cars feb 200
3 cars mar 300
3 cars apr 400
3 cars may 500
3 cars jun 600

© Copyright 2018–2024 Stichting DuckDB Foundation
Licensed under the MIT License.
https://duckdb.org/docs/internals/pivot.html

Spec-Zone.ru

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