Тип таблицы CONNECT PIVOT
Этот тип таблицы может быть использован для преобразования результата другой таблицы или представления (называемой исходной таблицей) в сводную таблицу по столбцам «pivot» и «facts». Сводная таблица — это удобный инструмент для отчётов, который сортирует и суммирует (по умолчанию) независимо от исходной структуры данных в исходной таблице.
Например, предположим, что у вас есть следующая таблица «Expenses»:
| Кто | Неделя | Что | Сумма |
|---|---|---|---|
| Джо | 3 | Пиво | 18.00 |
| Бет | 4 | Еда | 17.00 |
| Джейн | 5 | Пиво | 14.00 |
| Джо | 3 | Еда | 12.00 |
| Джо | 4 | Пиво | 19.00 |
| Джейн | 5 | Машина | 12.00 |
| Джо | 3 | Еда | 19.00 |
| Бет | 4 | Пиво | 15.00 |
| Джейн | 5 | Пиво | 19.00 |
| Джо | 3 | Машина | 20.00 |
| Джо | 4 | Пиво | 16.00 |
| Бет | 5 | Еда | 12.00 |
| Бет | 3 | Пиво | 16.00 |
| Джо | 4 | Еда | 17.00 |
| Джо | 5 | Пиво | 14.00 |
| Джейн | 3 | Машина | 19.00 |
| Джо | 4 | Еда | 17.00 |
| Бет | 5 | Пиво | 20.00 |
| Джейн | 3 | Еда | 18.00 |
| Джо | 4 | Пиво | 14.00 |
| Джо | 5 | Еда | 12.00 |
| Джейн | 3 | Пиво | 18.00 |
| Джейн | 4 | Машина | 17.00 |
| Джейн | 5 | Еда | 12.00 |
Преобразование содержимого таблицы, используя поля «Кто» и «Неделя» для левых столбцов, и поле «Что» для верхних заголовков, а также суммирование полей «Сумма» для каждой ячейки в новой таблице, даёт следующий желаемый результат:
| Кто | Неделя | Пиво | Машина | Еда |
|---|---|---|---|---|
| Бет | 3 | 16.00 | 0.00 | 0.00 |
| Бет | 4 | 15.00 | 0.00 | 17.00 |
| Бет | 5 | 20.00 | 0.00 | 12.00 |
| Джейн | 3 | 18.00 | 19.00 | 18.00 |
| Джейн | 4 | 0.00 | 17.00 | 0.00 |
| Джейн | 5 | 19.00 | 12.00 | 12.00 |
| Джо | 3 | 18.00 | 20.00 | 31.00 |
| Джо | 4 | 19.00 | 0.00 | 34.00 |
| Джо | 5 | 14.00 | 0.00 | 12.00 |
Обратите внимание, что SQL позволяет получить тот же результат, но по-другому, используя предложение «group by»:
select who, week, what, sum(amount) from expenses
group by who, week, what;
Однако нет способа получить представленную выше сводную структуру только с помощью SQL. Даже использование встроенного SQL-программирования для некоторых СУБД не совсем просто и автоматизировано.
Тип сводной таблицы CONNECT делает это намного проще.
Использование типа сводных таблиц
Чтобы получить результат, показанный в примере выше, просто определите его как новую таблицу с помощью оператора:
create table pivex engine=connect table_type=pivot tabname=expenses;
Теперь вы можете использовать её как любую другую таблицу, например, для отображения результата, показанного выше, просто скажите:
select * from pivex;
Реализация типа сводной таблицы CONNECT выполняет большую часть работы по преобразованию исходной таблицы:
- Нахождение столбца «Facts», по умолчанию последний столбец исходной таблицы. Нахождение столбцов «Facts» или «Pivot» работает только для сводных таблиц на основе таблиц. Они не работают для сводных таблиц на основе представлений или srcdef, для которых они должны быть явно указаны.
- Нахождение столбца «Pivot», по умолчанию оставшийся столбец.
- Выбор агрегатной функции для использования, «SUM» по умолчанию.
- Построение и выполнение «Group By» по столбцу «Facts», получение результата в памяти.
- Получение всех уникальных значений в столбце «Pivot» и определение столбца «Data» для каждого.
- Распространение результата промежуточной таблицы памяти в итоговую таблицу.
Столбец «Pivot» исходной таблицы не должен быть nullable (нет таких вещей как столбец «null»). Создание будет отклонено, даже если этот nullable столбец фактически не содержит нулевых значений.
Если требуется другой результат, доступны параметры Create Table для изменения значений по умолчанию, используемых Pivot. Например, если мы хотим отобразить средние расходы для каждого человека и продукта, распределённые по столбцам для каждой недели, используйте следующий оператор:
create table pivex2 engine=connect table_type=pivot tabname=expenses option_list='PivotCol=Week,Function=AVG';
Теперь, сказав:
select * from pivex2;
Будет отображена результирующая таблица:
| Кто | Что | 3 | 4 | 5 |
|---|---|---|---|---|
| Бет | Пиво | 16.00 | 15.00 | 20.00 |
| Бет | Еда | 0.00 | 17.00 | 12.00 |
| Джейн | Пиво | 18.00 | 0.00 | 16.50 |
| Джейн | Машина | 19.00 | 17.00 | 12.00 |
| Джейн | Еда | 18.00 | 0.00 | 12.00 |
| Джо | Пиво | 18.00 | 16.33 | 14.00 |
| Джо | Машина | 20.00 | 0.00 | 0.00 |
| Джо | Еда | 15.50 | 17.00 | 12.00 |
Ограничение столбцов в сводной таблице
Предположим, что нам нужна сводная таблица расходов, суммирующая расходы всех людей и продуктов независимо от недели покупки. Это можно сделать, просто удалив столбец недели из списка столбцов в таблице pivex.
alter table pivex drop column week;
Результат, который мы получаем от новой таблицы:
| Кто | Пиво | Машина | Еда |
|---|---|---|---|
| Бет | 51.00 | 0.00 | 29.00 |
| Джейн | 51.00 | 48.00 | 30.00 |
| Джо | 81.00 | 20.00 | 77.00 |
Примечание: Ограничение столбцов также необходимо, когда исходная таблица содержит дополнительные столбцы, которые не должны быть частью сводной таблицы. Это особенно верно для ключевых столбцов, которые препятствуют правильному группированию.
Синтаксис оператора CREATE TABLE для сводных таблиц
Оператор CREATE TABLE для сводных таблиц использует следующий синтаксис:
create table pivot_table_name
[(column_definition)]
engine=CONNECT table_type=PIVOT
{tabname='source_table_name' | srcdef='source_table_def'}
[option_list='pivot_table_option_list'];
Определение столбцов имеет два набора столбцов:
- Набор столбцов, принадлежащих исходной таблице, не включая столбцы «facts» и «pivot».
- Столбцы «Data», получающие значения агрегированных столбцов «facts», имеющие названия из значений столбца «pivot». Они обозначаются опцией «flag».
Доступные опции и подопции для сводных таблиц:
| Опция | Тип | Описание |
|---|---|---|
| ИмяТаблицы | [БД.]Имя | Имя таблицы для «свода». Если не задано, SrcDef должно быть указано. |
| SrcDef | SQL_оператор | Оператор, используемый для создания промежуточной mysql таблицы. |
| ИмяБД | имя | Имя базы данных, содержащей исходную таблицу. По умолчанию используется текущая база данных. |
| Функция* | имя | Имя агрегатной функции, используемой для столбцов данных, SUM по умолчанию. |
| PivotCol* | имя | Указывает имя столбца Pivot, значения которого используются для заполнения столбцов «data», имеющих опцию «flag». |
| FncCol* | [func(]имя[)] | Указывает имя столбца данных «Facts». Если используется форма func(имя), имя агрегатной функции устанавливается в func. |
| Groupby* | Булево | Установите его в True (1 или Yes), если таблица уже имеет формат GROUP BY. |
| Accept* | Булево | Принимать несовпадающие значения столбца Pivot. |
- : Эти опции должны быть указаны в OPTION_LIST.
Дополнительные параметры доступа
Существует четыре случая, когда Pivot должен вызывать сервер, содержащий исходную таблицу, или на котором должен быть выполнен оператор SrcDef:
1. Исходная таблица не является таблицей CONNECT. 2. Указана опция SrcDef. 3. Исходная таблица находится на другом сервере. 4. Столбцы не указаны.
По умолчанию Pivot пытается вызвать текущий сервер, используя host=localhost, user=root без пароля и port=3306. Однако это может не соответствовать требованиям, особенно если у локального пользователя root есть пароль, в этом случае может появиться сообщение об ошибке «access denied» при создании или использовании сводной таблицы.
Укажите опции host, user, password и/или port в списке параметров, чтобы переопределить параметры подключения по умолчанию, используемые для доступа к исходной таблице, получения спецификаций столбцов, выполнения сгенерированного запроса group by или SrcDef.
Определение сводной таблицы
Существуют два основных способа определения сводной таблицы:
1. Из существующей таблицы или представления. 2. Непосредственно указав SQL-оператор, возвращающий результат в Pivot.
Определение сводной таблицы из исходной таблицы
Стандартная опция таблицы tabname используется для указания имени исходной таблицы или представления.
Для таблиц внутренний Group By будет генерироваться внутри, за исключением случаев, когда опция GROUPBY задана как true. Делайте это только тогда, когда таблица или представление имеет правильный формат GROUP BY.
Непосредственное определение источника сводной таблицы в SQL
В качестве альтернативы, внутренний источник может быть непосредственно определён с помощью опции SrcDef, которая должна иметь правильный формат group by.
Как мы видели выше, правильная сводная таблица создаётся из внутренней промежуточной таблицы, полученной в результате выполнения оператора GROUP BY. Во многих случаях проще или желательно указать это напрямую при создании сводной таблицы. Это может быть потому, что источник является результатом сложного процесса, включающего фильтрацию и/или объединение таблиц.
Для этого используйте опцию SrcDef, часто заменяя все остальные опции. Например, предположим, что в первом примере нас интересуют только недели 4 и 5. Мы можем, конечно, отобразить это, используя:
select * from pivex where week in (4,5);
Однако, что если эта таблица огромна? В этом случае правильный способ сделать это — определить сводную таблицу следующим образом:
create table pivex4 engine=connect table_type=pivot option_list='PivotCol=what,FncCol=amount' SrcDef='select who, week, what, sum(amount) from expenses where week in (4,5) group by who, week, what';
Если ваша исходная таблица содержит миллионы записей, а вы планируете преобразовать только небольшую часть из них, это существенно повлияет на производительность. Кроме того, вы имеете полную свободу использовать выражения, скалярные функции, псевдонимы, объединения, условия where и having в вашем SQL-запросе. Единственное ограничение заключается в том, что вы несете ответственность за то, чтобы результат этого запроса имел правильный формат для обработки сводки.
Использование SrcDef также позволяет использовать выражения и/или скалярные функции. Например:
create table xpivot ( Who char(10) not null, What char(12) not null, First double(8,2) flag=1, Middle double(8,2) flag=1, Last double(8,2) flag=1) engine=connect table_type=PIVOT option_list='PivotCol=wk,FncCol=amnt' Srcdef='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk';
Теперь запрос:
select * from xpivot;
Выведет результат:
| Кто | Что | Первый | Средний | Последний |
|---|---|---|---|---|
| Beth | Пиво | 104.96 | 98.40 | 131.20 |
| Beth | Еда | 0.00 | 111.52 | 78.72 |
| Janet | Пиво | 118.08 | 0.00 | 216.48 |
| Janet | Авто | 124.64 | 111.52 | 78.72 |
| Janet | Еда | 118.08 | 0.00 | 78.72 |
| Joe | Пиво | 118.08 | 321.44 | 91.84 |
| Joe | Авто | 131.20 | 0.00 | 0.00 |
| Joe | Еда | 203.36 | 223.04 | 78.72 |
Примечание 1: чтобы избежать нескольких строк с одинаковыми значениями фиксированных столбцов, в SrcDef обязательно следует размещать столбец сводки в конце списка group by.
Примечание 2: в операторе создания SrcDef обязательно необходимо присваивать псевдонимы столбцам, содержащим выражения, чтобы они распознавались другими опциями.
Примечание 3: в операторе выбора SrcDef кавычки необходимо экранировать, поскольку весь оператор передаётся MariaDB в кавычках. В качестве альтернативы, укажите его в двойных кавычках.
Примечание 4: Мы могли бы оставить CONNECT для определения столбцов. Однако, поскольку они определены по отсортированным именам, столбец Средний был помещен в конец.
Указание столбцов, соответствующих столбцу сводки
Эти столбцы должны быть названы по значениям, присутствующим в столбце «pivot». Например, предположим, что у нас есть следующая таблица pet:
| Имя | Порода | Количество |
|---|---|---|
| John | собака | 2 |
| Bill | кот | 1 |
| Mary | собака | 1 |
| Mary | кот | 1 |
| Lisbeth | кролик | 2 |
| Kevin | кот | 2 |
| Kevin | птица | 6 |
| Donald | собака | 1 |
| Donald | рыба | 3 |
Преобразование его с использованием Порода в качестве столбца сводки выполняется с помощью:
create table pivet engine=connect table_type=pivot tabname=pet option_list='PivotCol=race,groupby=1';
Это даёт результат:
| Имя | Собака | Кот | Кролик | Птица | Рыба |
|---|---|---|---|---|---|
| John | 2 | 0 | 0 | 0 | 0 |
| Bill | 0 | 1 | 0 | 0 | 0 |
| Mary | 1 | 1 | 0 | 0 | 0 |
| Lisbeth | 0 | 0 | 2 | 0 | 0 |
| Kevin | 0 | 2 | 0 | 6 | 0 |
| Donald | 1 | 0 | 0 | 0 | 3 |
Кстати, это вам о чём-то говорит? Это показывает, что сводные таблицы в некотором роде выполняют обратные действия по сравнению с таблицами OCCUR.
Мы можем альтернативно определить конкретно столбцы таблицы, но что произойдёт, если столбец Сводки содержит значения, не соответствующие столбцу «данных»? Существует три случая в зависимости от указанных параметров и флагов.
Первый случай: Если не указано никаких конкретных параметров, это ошибка, и при попытке отобразить таблицу запрос прервётся с сообщением об ошибке, указывающим, что было встречено несоответствующее значение. Обратите внимание, что поскольку список столбцов формируется при создании таблицы, это может произойти, если в исходную таблицу вставлены строки, содержащие новые значения для столбца сводки. В этом случае следует пересоздать таблицу или вручную добавить новые столбцы в сводную таблицу.
Второй случай: был указан параметр accept. Например:
create table xpivet2 ( name varchar(12) not null, dog int not null default 0 flag=1, cat int not null default 0 flag=1) engine=connect table_type=pivot tabname=pet option_list='PivotCol=race,groupby=1,Accept=1';
Ошибка не будет поднята, и несоответствующие значения будут проигнорированы. Эта таблица будет отображена как:
| Имя | Собака | Кот |
|---|---|---|
| John | 2 | 0 |
| Bill | 0 | 1 |
| Mary | 1 | 1 |
| Lisbeth | 0 | 0 |
| Kevin | 0 | 2 |
| Donald | 1 | 0 |
Третий случай: был указан столбец «dump» со значением флага, равным 2. Все несоответствующие значения будут добавлены в этот столбец. Например:
create table xpivet ( name varchar(12) not null, dog int not null default 0 flag=1, cat int not null default 0 flag=1, other int not null default 0 flag=2) engine=connect table_type=pivot tabname=pet option_list='PivotCol=race,groupby=1';
Эта таблица будет отображена как:
| Имя | Собака | Кот | Другое |
|---|---|---|---|
| John | 2 | 0 | 0 |
| Bill | 0 | 1 | 0 |
| Mary | 1 | 1 | 0 |
| Lisbeth | 0 | 0 | 2 |
| Kevin | 0 | 2 | 6 |
| Donald | 1 | 0 | 3 |
Полезно предоставить такой столбец «dump», если исходная таблица подвержена вставке новых строк, которые могут иметь значение для столбца сводки, которое отсутствовало при создании сводной таблицы.
Преобразование больших исходных таблиц
Это иногда может быть рискованно. Если столбец сводки содержит слишком много различных значений, результирующая таблица может иметь слишком много столбцов. Во всех случаях, процесс поиска уникальных значений при создании таблицы или выполнении группировки при её использовании может быть очень долгим и иногда может завершиться неудачно из-за недостатка памяти.
Ограничения с помощью условия where должны применяться к исходной таблице при создании сводной таблицы, а не к самой сводной таблице. Это можно сделать, создав промежуточную таблицу или используя в качестве источника представление или параметр srcdef.
Все сводные таблицы являются только для чтения.
© 2023 MariaDB
Licensed under the Creative Commons Attribution 3.0 Unported License and the GNU Free Documentation License.
https://mariadb.com/kb/en/connect-pivot-table-type/