У меня есть существующая таблица, например:
CREATE TABLE ES_DEVISES (
NOM VARCHAR2(500),
DEVISE VARCHAR2(5),
ORDRES NUMBER(5,0)
)
-- For testing purposes :
INSERT INTO ES_DEVISES VALUES ('ES1','CHF',157);
INSERT INTO ES_DEVISES VALUES ('ES1','USD',1328);
INSERT INTO ES_DEVISES VALUES ('ES2','AUD',5);
INSERT INTO ES_DEVISES VALUES ('ES1','AUD',23);
INSERT INTO ES_DEVISES VALUES ('ES1','CNY',17);
INSERT INTO ES_DEVISES VALUES ('ES1','INR',17);
INSERT INTO ES_DEVISES VALUES ('ES2','CNY',1);
INSERT INTO ES_DEVISES VALUES ('ES2','INR',4);
INSERT INTO ES_DEVISES VALUES ('ES2','USD',218);
INSERT INTO ES_DEVISES VALUES ('ES2','CHF',42);
И у меня есть то, что выводит строки в такие столбцы, что возвращает желаемый результат:
SELECT * FROM ES_DEVISES
PIVOT (
MAX(ORDRES) FOR DEVISE IN ('USD' USD,'CHF' CHF,'CNY' CNY,'INR' INR,'AUD' AUD)
);
-- Output :
NOM USD CHF CNY INR AUD
---------------- ---------- ---------- ---------- ---------- ----------
ES1 1328 157 17 17 23
ES2 218 42 1 4 5
Теперь, с некоторой эволюцией, таблица ES_DEVISES
будет содержать случайные единицы (ES1, ES2, ES3, ...) и случайные валюты (USD, EUR, XRP, BTC, ...), поэтому приведенный выше запрос выиграет больше не будет действительным. Я нашел этот ответ , который рекомендует использовать PIVOT XML
, поэтому запрос стал:
SELECT NOM, DEVISE_XML
FROM ES_DEVISES
PIVOT XML(
MAX(ORDRES) FOR DEVISE IN (SELECT DEVISE FROM NEW_TABLE_FOR_CURRENCIES)
) t;
-- Output :
NOM DEVISE_XML
---------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ES1 <PivotSet><item><column name = "DEVISE">AUD</column><column name = "MAX(ORDRES)">23</column></item><item><column name = "DEVISE">CHF</column><column name = "MAX(ORDRES)">157</column></item><item><column name = "DEVISE">CNY</column><column name = "MAX(ORDRES)">17</column></item><item><column name = "DEVISE">INR</column><column name = "MAX(ORDRES)">17</column></item><item><column name = "DEVISE">USD</column><column name = "MAX(ORDRES)">1328</column></item></PivotSet>
ES2 <PivotSet><item><column name = "DEVISE">AUD</column><column name = "MAX(ORDRES)">5</column></item><item><column name = "DEVISE">CHF</column><column name = "MAX(ORDRES)">42</column></item><item><column name = "DEVISE">CNY</column><column name = "MAX(ORDRES)">1</column></item><item><column name = "DEVISE">INR</column><column name = "MAX(ORDRES)">4</column></item><item><column name = "DEVISE">USD</column><column name = "MAX(ORDRES)">218</column></item></PivotSet>
Следующим шагом сейчас является анализ этого XML, чтобы я мог вернуться к результирующему набору, который выглядит как первый вывод. Проблема в том, что поле DEVISE_XML
не содержит поля NOM
, и я не смог найти способ разбора XML на динамические столбцы, я попытался использовать XMLTABLE
, но он возвращает меня к чему-то вроде SELECT * FROM ES_DEVISES
.
Мой вопрос: есть ли способ либо:
1) вернуть XML, похожий на этот:
<PivotSet>
<row>
<unit>ES1</unit>
<column name="AUD">23</column>
<column name="CHF">157</column>
<column name="CNY">17</column>
<column name="INR">17</column>
<column name="USD">1328</column>
</row>
<row>
<unit>ES2</unit>
<column name="AUD">218</column>
<column name="CHF">42</column>
<column name="CNY">1</column>
<column name="INR">4</column>
<column name="USD">5</column>
</row>
</PivotSet>
2) Анализирует XML для динамического возврата желаемого результата (который должен выглядеть как результат первого запроса).
PS: я видел много решений в сети, таких как LISTAGG
или построение запроса со строкой и выполнение его с EXECUTE IMMEDIATE
. Но ничего из этого меня не интересует, потому что я мог бы легко сделать это с JAVA, но цель этого вопроса - найти понятный, легко обслуживаемый запрос, который выполняет всю работу с PROCEDURE
.