2016-08-01 10 views
2

Я хочу создать таблицу, в которой записи из разных столбцов будут «повернуты» к заголовкам столбцов. Таблица предназначена для целей отчетности - мои пользователи хотят запрашивать данные через 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.

+0

обратитесь по этой ссылке 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 $')) ** –

+0

Динамический Sql - это именно тот путь, который вам нужно, когда вам нужно поворачивать поля которые определяются пользователем во время выполнения.Создайте функцию VBA, которая будет строить текст команды Sql в соответствии с выбором пользователя. – Serg

+2

Я думаю, что «документация», которую вы нашли, неверна. Если вы обратитесь к [официальной документации] (https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#CHDFAFIE), вы увидите, что параметр подзапроса разрешен только в сочетании с ключевым словом XML. – jpw

ответ

4

Вы можете поворачиваться на нескольких столбцах, заключая столбцы, и множество значений, в скобках:

SELECT * FROM 
(
    SELECT * FROM tt 
) 
PIVOT 
(
    SUM(PRICE) 
    FOR (MARKET, BID_ASK) 
    IN (('US', 'Bid') us_bid, ('US', 'Ask') us_ask, ('EU', 'Bid') eu_bid, ('EU', 'Ask') eu_ask) 
); 

COMMODITY  US_BID  US_ASK  EU_BID  EU_ASK 
---------- ---------- ---------- ---------- ---------- 
Gold    1  1.1  1.1  1.2 
Oil    10   11   11   12 

но пары значений по-прежнему должны быть известны, когда запрос обрабатывается, и это Безразлично» t хорошо, если у вас много комбинаций значений.

Ваша единственная альтернатива - это динамический SQL, как вы подозревали, если только вы не можете заставить Excel обрабатывать результат XML-свода, который, как я думаю, невозможен. С динамическим SQL вы могли бы иметь функцию, которая выполняет запрос и сворачивает, и возвращает курсор ref, если Excel считает, что его проще обрабатывать, чем сводный запрос.

Смежные вопросы