web-dev-qa-db-ja.com

Oracleでの行の列への動的なピボット

_kvという次のOracle 10gテーブルがあります。

select * from _kv

ID       K       V
----     -----   -----
  1      name    Bob
  1      age     30
  1      gender  male
  2      name    Susan
  2      status  married

PL/SQLではなくプレーンSQLを使用してキーを列に変換して、結果の表が次のようになるようにします。

ID       NAME    AGE    GENDER  STATUS
----     -----   -----  ------  --------
  1      Bob      30     male 
  2      Susan                   married
  • クエリには、テーブルに存在する一意のKsと同じ数の列が必要です(それほど多くはありません)
  • クエリを実行する前に、どの列が存在するかを知る方法はありません。
  • プログラムで最終的なクエリを作成するために、最初のクエリを実行しないようにしています。
  • 空白のセルは、nullまたは空の文字列の場合がありますが、実際には問題ではありません。
  • Oracle 10gを使用していますが、11gのソリューションでも問題ありません。

ピボット列の名前を知っている場合の例はたくさんありますが、Oracleの一般的なピボットソリューションは見つかりません。

ありがとう!

24
ojosilva

Oracle 11gは、必要なことを行うPIVOT操作を提供します。

Oracle 11gソリューション

_select * from
(select id, k, v from _kv) 
pivot(max(v) for k in ('name', 'age', 'gender', 'status')
_

(注:これをテストする11gのコピーがないため、機能を確認していません)

私はこのソリューションを以下から入手しました: http://orafaq.com/wiki/PIVOT

EDIT-ピボットxmlオプション(Oracle 11gも)
明らかに、必要な可能性のあるすべての列見出しがわからない場合の_pivot xml_オプションもあります。 (XML TYPEセクションを参照してください http://www.Oracle.com/technetworkにあるページの下部にあります) /articles/sql/11g-pivot-097235.html

_select * from
(select id, k, v from _kv) 
pivot xml (max(v)
for k in (any) )
_

(注:以前と同様に、これをテストする11gのコピーがないため、機能を確認していません)

Edit2:vおよび_pivot xml_ステートメントのpivotmax(v)に変更コメントの1つで言及されているように集約されることになっています。 inのオプションではないpivot句も追加しました。もちろん、in句で値を指定する必要があるため、この質問のポスターの要望通り、完全に動的なピボット/クロス集計クエリを作成するという目標は無効になります。

30
dave

複数の値(例ではv)の可能性がある状況に対処するために、PIVOTLISTAGGを使用します。

SELECT * FROM
(
  SELECT id, k, v
  FROM _kv 
)
PIVOT 
(
  LISTAGG(v ,',') 
  WITHIN GROUP (ORDER BY k) 
  FOR k IN ('name', 'age','gender','status')
)
ORDER BY id;

動的な値が必要なため、動的SQLを使用して、ピボットステートメントを呼び出す前にテーブルデータでselectを実行することで決定された値を渡します。

6
eniacAvenger

ピボットにタスクがあるようになります。以下は、11gで今テストしたとおりに機能します。

select * from
(
  select ID, COUNTRY_NAME, TOTAL_COUNT from ONE_TABLE 
) 
pivot(
  SUM(TOTAL_COUNT) for COUNTRY_NAME in (
    'Canada', 'USA', 'Mexico'
  )
);
5
Herbert Yu

まず、pivot xmlを使用した動的なピボットを再度解析する必要があります。これを行う別の方法として、列名を変数に保存し、以下のように動的SQLに渡します。

下のような表があると考えてください。

enter image description here

YR列の値を列名として表示し、QTYの列の値を表示する必要がある場合、以下のコードを使用できます。

declare
  sqlqry clob;
  cols clob;
begin
  select listagg('''' || YR || ''' as "' || YR || '"', ',') within group (order by YR)
  into   cols
  from   (select distinct YR from EMPLOYEE);


  sqlqry :=
  '      
  select * from
  (
      select *
      from EMPLOYEE
  )
  pivot
  (
    MIN(QTY) for YR in (' || cols  || ')
  )';

  execute immediate sqlqry;
end;
/

[〜#〜] result [〜#〜]

enter image description here

3
Sarath Avanavu