19

... pivot (sum(A) for B in (X))

ここで、B はデータ型 varchar2 であり、X はカンマで区切られた varchar2 値の文字列です。
X の値は、同じテーブルの列 (CL など) から個別の値を選択したものです。この方法でピボットクエリが機能していました。

しかし、問題は、列 CL に新しい値があるたびに、それを文字列 X に手動で追加する必要があることです。

X を CL から個別の値を選択して置き換えてみました。しかし、クエリは実行されていません。
私が感じた理由は、X を置き換えるにはコンマで区切られた値が必要であるという事実によるものでした。
次に、文字列 X と一致する正確な出力を返す関数を作成しましたが、クエリはまだ実行されません。
表示されるエラー メッセージは、"missing righr parantheses"、"end of file communication channel" などです。
単にピボットする代わりにピボット xml を試しましたが、クエリは実行されますが、まったく値のない oraxxx などの値が返されます。

たぶん私はそれを適切に使用していません。
動的な値でピボットを作成する方法を教えてください。

4

10 に答える 10

23

PIVOT XML を使用せずに、PIVOT の IN ステートメントに動的ステートメントを入れることはできません。これは、望ましくない出力を出力します。ただし、IN 文字列を作成してステートメントに入力することはできます。

まず、これが私のサンプル テーブルです。

  myNumber    myValue myLetter
---------- ---------- --------
         1          2 A        
         1          4 B        
         2          6 C        
         2          8 A        
         2         10 B        
         3         12 C        
         3         14 A      

まず、IN ステートメントで使用する文字列をセットアップします。ここでは、文字列を「str_in_statement」に入れています。COLUMN NEW_VALUELISTAGGを使用して文字列を設定しています。

clear columns
COLUMN temp_in_statement new_value str_in_statement
SELECT DISTINCT 
    LISTAGG('''' || myLetter || ''' AS ' || myLetter,',')
        WITHIN GROUP (ORDER BY myLetter) AS temp_in_statement 
    FROM (SELECT DISTINCT myLetter FROM myTable);

文字列は次のようになります。

'A' AS A,'B' AS B,'C' AS C

次に、PIVOT クエリで String ステートメントを使用します。

SELECT * FROM 
    (SELECT myNumber, myLetter, myValue FROM myTable)
    PIVOT (Sum(myValue) AS val FOR myLetter IN (&str_in_statement));

出力は次のとおりです。

  MYNUMBER      A_VAL      B_VAL      C_VAL
---------- ---------- ---------- ----------
         1          2          4            
         2          8         10          6 
         3         14                    12 

ただし、制限があります。連結できる文字列は 4000 バイトまでです。

于 2014-05-16T15:16:49.817 に答える
17

INピボット句の句に非定数文字列を入れることはできません。
そのために Pivot XML を使用できます。

ドキュメントから:

subquery サブクエリは、XML キーワードと組み合わせてのみ使用されます。サブクエリを指定すると、サブクエリで見つかったすべての値がピボットに使用されます

次のようになります。

select xmlserialize(content t.B_XML) from t_aa
pivot xml(
sum(A) for B in(any)
) t;

ANYキーワードの代わりにサブクエリを使用することもできます。

select xmlserialize(content t.B_XML) from t_aa
pivot xml(
sum(A) for B in (select cl from t_bb)
) t;

ここにsqlfiddleのデモがあります

于 2013-03-19T05:49:01.217 に答える
1

上記の方法 (Anton PL/SQL カスタム関数 pivot()) を使用したところ、うまくいきました。私はプロの Oracle 開発者ではないので、これらは私が行った簡単な手順です。

1) zip パッケージをダウンロードして、pivotFun.sql を見つけます。2) pivotFun.sql を 1 回実行して、新しい関数を作成します。3) 通常の SQL で関数を使用します。

動的な列名には注意してください。私の環境では、列名が 30 文字に制限されており、単一引用符を含めることができないことがわかりました。したがって、私のクエリは次のようになります。

SELECT 
  *
FROM   
  table( 
        pivot('
                SELECT DISTINCT
                    P.proj_id,
                    REPLACE(substr(T.UDF_TYPE_LABEL, 1, 30), '''''''','','') as Attribute,
                    CASE
                      WHEN V.udf_text is null     and V.udf_date is null and      V.udf_number is NOT null  THEN to_char(V.udf_number)
                      WHEN V.udf_text is null     and V.udf_date is NOT null and  V.udf_number is null      THEN to_char(V.udf_date)
                      WHEN V.udf_text is NOT null and V.udf_date is null and      V.udf_number is null      THEN V.udf_text
                      ELSE NULL END
                    AS VALUE
                FROM
                    project   P
                LEFT JOIN UDFVALUE V ON P.proj_id     = V.proj_id 
                LEFT JOIN UDFTYPE  T ON V.UDF_TYPE_ID = T.UDF_TYPE_ID
                WHERE 
                    P.delete_session_id  IS NULL AND
                    T.TABLE_NAME = ''PROJECT''
    ')
)

最大 1m のレコードでうまく機能します。

于 2016-11-11T02:39:21.880 に答える
0

PIVOT XMLを使わずにPIVOTのIN文に動的文を入れることはできませんが、ちょっとしたテクニックを使えばPIVOTで動的文を使うことができます。PL/SQL では、文字列値内で、2 つのアポストロフィは 1 つのアポストロフィと同じです。

declare
  sqlqry clob;   
  search_ids  varchar(256) := '''2016'',''2017'',''2018'',''2019''';
begin
  search_ids := concat( search_ids,'''2020''' ); -- you can append new search id dynamically as you wanted
  sqlqry :=
  '      
  select * from
  (
      select *
      from EMPLOYEE
  )
  pivot
  (
    MIN(QTY) for YR in (' || search_ids   || ')
  )';

  execute immediate sqlqry;
end;
于 2020-05-12T18:13:49.830 に答える