Я хочу создать таблицу, в которой записи из разных столбцов будут «повернуты» к заголовкам столбцов. Таблица предназначена для целей отчетности - мои пользователи хотят запрашивать данные через Excel (используя Microsoft Query), и проблема в том, что выполнение поворота в Excel делает файлы непрактично большими и медленными даже для наборов данных умеренного размера (~ 100 тыс. Точек данных).Oracle SQL: Pivot на нескольких столбцах/полях
Рассмотрим следующий пример:
CREATE TABLE tt
(
"COMMODITY" VARCHAR2(4000 BYTE),
"MARKET" VARCHAR2(4000 BYTE),
"BID_ASK" VARCHAR2(4000 BYTE),
"PRICE" NUMBER
);
INSERT INTO tt VALUES ('Gold','US','Ask',1.1);
INSERT INTO tt VALUES ('Gold','US','Bid',1);
INSERT INTO tt VALUES ('Gold','EU','Ask',1.2);
INSERT INTO tt VALUES ('Gold','EU','Bid',1.1);
INSERT INTO tt VALUES ('Oil','US','Ask',11);
INSERT INTO tt VALUES ('Oil','US','Bid',10);
INSERT INTO tt VALUES ('Oil','EU','Ask',12);
INSERT INTO tt VALUES ('Oil','EU','Bid',11);
Вывод, который я хочу, чтобы достичь было бы что-то вроде (точные заголовки столбцов не имеет большого значения):
COMMODITY 'US_Bid' 'US_Ask' 'EU_Bid' 'EU_Ask'
Gold 1 1.1 1.1 1.2
Oil 10 11 11 12
Теперь это просто для поворота одной колонки:
SELECT * FROM
(
SELECT * FROM tt
)
PIVOT
(
SUM(PRICE)
FOR MARKET IN ('US','EU')
)
Что дает:
COMMODITY BID_ASK 'US' 'EU'
Gold Bid 1 1.1
Oil Bid 10 11
Oil Ask 11 12
Gold Ask 1.1 1.2
Согласно моим исследованиям нет синтаксиса для прямого поворота нескольких столбцов. Есть некоторые связанные вопросы (here, here или here), но я не мог найти прямой ответ на мою проблему. Поэтому я придумал следующее решение:
SELECT * FROM
(
SELECT COMMODITY, CONCAT(CONCAT(MARKET,'_'),BID_ASK) AS MARKET_BID_ASK, PRICE FROM tt
)
PIVOT
(
SUM(PRICE)
FOR MARKET_BID_ASK IN ('US_Bid','US_Ask','EU_Bid','EU_Ask')
)
Это производит точно нужный результат. Тем не менее, я не считаю это практическим решением, так как число переменных, которые мне нужно вводить, растет слишком быстро (в моем реальном наборе данных я хочу поочередно создавать больше полей, все из которых имеют много разных значений). Я знаю, что существует dynamic pivots, однако я не уверен, будет ли это работать с Excel, и я также хотел бы, чтобы синтаксис был как можно более простым, потому что пользователи сами будут определять запросы (я просто хочу предоставить шаблон запрос, который они могут адаптировать). Так что я попытался запросить имена полей в IN-п:
SELECT * FROM
(
SELECT COMMODITY, CONCAT(CONCAT(MARKET,'_'),BID_ASK) AS MARKET_BID_ASK, PRICE FROM tt
)
PIVOT
(
SUM(PRICE)
FOR MARKET_BID_ASK IN
(
SELECT DISTINCT CONCAT(CONCAT(MARKET,'_'),BID_ASK) AS MARKET_BID_ASK FROM tt
)
)
Я думаю, что такое решение может быть практичным, так как можно было бы еще ограничить переменные запрошенные без перечислить все сцепленные варианты с использованием как- условия в подзапросе. Тем не менее, я получаю сообщение об ошибке «ORA-00936 - missing expression» с этим запросом, хотя подзапросы должны быть законными здесь в соответствии с найденным мной documentation.
обратитесь по этой ссылке http://stackoverflow.com/questions/38651147/how-to-transpose-column-into-row-in-oracle-sql-11g/38653133#38653133 и попробуйте с ** select * from table (pivot (Q '$ SELECT COMMODITY, CONCAT (CONCAT (MARKET,' _ '), BID_ASK) AS MARKET_BID_ASK, ЦЕНА ОТ tt $')) ** –
Динамический Sql - это именно тот путь, который вам нужно, когда вам нужно поворачивать поля которые определяются пользователем во время выполнения.Создайте функцию VBA, которая будет строить текст команды Sql в соответствии с выбором пользователя. – Serg
Я думаю, что «документация», которую вы нашли, неверна. Если вы обратитесь к [официальной документации] (https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#CHDFAFIE), вы увидите, что параметр подзапроса разрешен только в сочетании с ключевым словом XML. – jpw