Внутреннее устройство 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