...ピボット((X)のBの合計(A))
現在、Bはデータ型varchar2であり、Xはコンマで区切られたvarchar2値の文字列です。
Xの値は、同じテーブルの列(CLなど)から個別の値を選択します。この方法でピボットクエリは機能していました。
しかし、問題は、列CLに新しい値があるたびに、それを文字列Xに手動で追加する必要があることです。
XをCLから選択した個別の値に置き換えてみました。しかし、クエリは実行されていません。
私が感じた理由は、Xを置き換えるには値をコンマで区切る必要があるという事実によるものでした。
次に、文字列Xと一致する正確な出力を返す関数を作成しました。しかし、クエリはまだ実行されません。
表示されるエラーメッセージは、「missing righr parantheses」、「end of file communication channel」などのようなものです。
。
たぶん私はそれを適切に使用していません。
動的な値を持つピボットを作成する方法を教えてください。
PIVOT XMLを使用せずに、PIVOTのINステートメントに動的ステートメントを配置することはできません。PIVOTXMLは、望ましい出力よりも低い出力を出力します。ただし、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_VALUE および [〜#〜] listagg [〜#〜] を使用して文字列を設定します。
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バイトです。
後の読者のために、ここに別のソリューションがあります https://technology.amis.nl/2006/05/24/dynamic-sql-pivoting-stealing-antons-thunder/
のようなクエリを許可する
select * from table( pivot( 'select deptno, job, count(*) c from scott.emp group by deptno,job' ) )
動的クエリを使用
テストコードは以下です
-- DDL for Table TMP_TEST
--------------------------------------------------------
CREATE TABLE "TMP_TEST"
( "NAME" VARCHAR2(20),
"APP" VARCHAR2(20)
);
/
SET DEFINE OFF;
Insert into TMP_TEST (NAME,APP) values ('suhaib','2');
Insert into TMP_TEST (NAME,APP) values ('suhaib','1');
Insert into TMP_TEST (NAME,APP) values ('shahzad','3');
Insert into TMP_TEST (NAME,APP) values ('shahzad','2');
Insert into TMP_TEST (NAME,APP) values ('shahzad','5');
Insert into TMP_TEST (NAME,APP) values ('tariq','1');
Insert into TMP_TEST (NAME,APP) values ('tariq','2');
Insert into TMP_TEST (NAME,APP) values ('tariq','6');
Insert into TMP_TEST (NAME,APP) values ('tariq','4');
/
CREATE TABLE "TMP_TESTAPP"
( "APP" VARCHAR2(20)
);
SET DEFINE OFF;
Insert into TMP_TESTAPP (APP) values ('1');
Insert into TMP_TESTAPP (APP) values ('2');
Insert into TMP_TESTAPP (APP) values ('3');
Insert into TMP_TESTAPP (APP) values ('4');
Insert into TMP_TESTAPP (APP) values ('5');
Insert into TMP_TESTAPP (APP) values ('6');
/
create or replace PROCEDURE temp_test(
pcursor out sys_refcursor,
PRESULT OUT VARCHAR2
)
AS
V_VALUES VARCHAR2(4000);
V_QUERY VARCHAR2(4000);
BEGIN
PRESULT := 'Nothing';
-- concating activities name using comma, replace "'" with "''" because we will use it in dynamic query so "'" can effect query.
SELECT DISTINCT
LISTAGG('''' || REPLACE(APP,'''','''''') || '''',',')
WITHIN GROUP (ORDER BY APP) AS temp_in_statement
INTO V_VALUES
FROM (SELECT DISTINCT APP
FROM TMP_TESTAPP);
-- designing dynamic query
V_QUERY := 'select *
from ( select NAME,APP
from TMP_TEST )
pivot (count(*) for APP in
(' ||V_VALUES|| '))
order by NAME' ;
OPEN PCURSOR
FOR V_QUERY;
PRESULT := 'Success';
Exception
WHEN OTHERS THEN
PRESULT := SQLcode || ' - ' || SQLERRM;
END temp_test;
上記のメソッド(Anton PL/SQLカスタム関数ピボット())を使用して、仕事をしました!私はプロのOracle開発者ではないので、これらは私が行った簡単な手順です。
1)Zipパッケージをダウンロードして、pivotFun.sqlを見つけます。 2)pivotFun.sqlを一度実行して、新しい関数を作成します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のレコードでうまく機能します。
OPが尋ねた質問に正確に答えるつもりはありません。代わりに、動的ピボットをどのように行うことができるかを説明するだけです。
ここでは、最初に列の値を変数に取得し、動的SQL内で変数を渡すことにより、動的SQLを使用する必要があります。
[〜#〜] example [〜#〜]
下のような表があると考えてください。
列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 [〜#〜]
必要に応じて、一時テーブルを作成し、その一時テーブルで選択クエリを実行して結果を確認することもできます。その単純な、単にCREATE TABLE TABLENAME AS
上記のコード。
sqlqry :=
'
CREATE TABLE TABLENAME AS
select * from