さまざまな列のエントリが列ヘッダーに「ピボット」されるテーブルを作成したいと思います。この表はレポート用です-ユーザーはExcel経由で(Microsoft Queryを使用して)データをクエリしたいのですが、問題は、Excelでピボットを実行すると、中程度のサイズのデータセット(約100kデータポイント)でもファイルが非実用的に大きくなり、遅くなることです。 )。
次の例を考えてみましょう。
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
私の調査によると、複数の列を直接ピボットするための構文はありません。関連する質問がいくつかあります( ここ 、 ここ または ここ )が、そこで私の問題に対する直接の答えを見つけることができませんでした。だから私は次の解決策を思いついた:
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')
)
これにより、正確に目的の出力が生成されます。ただし、入力する必要のある変数の数が非常に速く増加するため、実用的な解決策とは考えていません(実際のデータセットでは、一度に多くのフィールドをピボットしたいので、すべてが多くの異なる値を持ちます)。 動的ピボット が存在することは知っていますが、これが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
)
)
サブクエリでLIKE条件を使用してすべての連結オプションをリストする必要がなくても、クエリされた変数を制約できるため、このようなソリューションは実用的であると思います。ただし、見つかった documentation によると、ここではサブクエリが有効であるはずなのに、このクエリで「ORA-00936-式がありません」というエラーが発生します。
列と値のセットを括弧で囲むことにより、複数の列をピボットできます。
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
ただし、クエリを解析するときは値のペアを知る必要があり、値の組み合わせが多い場合、これは適切にスケーリングされません。
あなたが疑ったように、あなたの唯一の選択肢は動的SQLです。ただし、ExcelにXMLピボットの結果を処理させることができない限り、これは不可能だと思います。動的SQLを使用すると、Excelがピボットクエリよりも処理しやすいと判断した場合に、クエリとピボットを実行して参照カーソルを返す関数を使用できます。