あなたは近いです - あなたが望むのは UNPIVOT
の組み合わせです および PIVOT
:
with T AS (
select 1 as element, 1.1 as reading1, 1.2 as reading2, 1.3 as reading3 from dual union all
select 2 as element, 2.1 as reading1, 2.2 as reading2, 2.3 as reading3 from dual union all
select 3 as element, 3.1 as reading1, 3.2 as reading2, 3.3 as reading3 from dual
)
select * from (
select * from t
unpivot (reading_value
for reading_name in ("READING1", "READING2", "READING3")
)
pivot(max(reading_value) for element in (1,2,3)
)
)
order by reading_name
このクエリ
- 列を変換します reading1、reading2、reading3 を別々の行に (名前は reading_name に入ります 、値を reading_value に );これにより、(element,reading_name) ごとに 1 行が得られます
- 行を変換します 1、2*、3 (要素の値 ) 列 '1'、'2'、'3' に。これにより、reading_name ごとに 1 つの行が得られます
更新
要素のリストが実行時までわからない場合 (たとえば、ユーザーがそれらを選択するオプションを持っているため)、より動的なアプローチが必要です。指定された要素のリストに対して SQL ステートメントを動的に作成し、sys_refcursor
を使用する 1 つのソリューションを次に示します。 結果セットのために。
-- setup table
create table T AS
select 1 as element, 1.1 as reading1, 1.2 as reading2, 1.3 as reading3 from dual union all
select 2 as element, 2.1 as reading1, 2.2 as reading2, 2.3 as reading3 from dual union all
select 3 as element, 3.1 as reading1, 3.2 as reading2, 3.3 as reading3 from dual ;
/
declare
l_Elements dbms_sql.Number_Table;
function pivot_it(p_Elements in dbms_sql.Number_Table)
return sys_refcursor is
l_SQL CLOB := empty_clob();
l_Result sys_refcursor;
begin
l_SQL := '
select * from (
select * from t
unpivot (reading_value
for reading_name in ("READING1", "READING2", "READING3")
)
pivot(max(reading_value) for element in (';
for i in 1 .. p_Elements.count
loop
l_SQL := l_SQL || to_char(p_Elements(i)) || ',';
end loop;
-- remove trailing ','
l_SQL := regexp_replace(l_SQL, ',$');
l_SQL := l_SQL || ')
)
)';
dbms_output.put_line(l_SQL);
open l_Result for l_SQL;
return l_Result;
end;
begin
l_Elements(1) := 1;
l_Elements(2) := 2;
-- uncomment this line to get all 3 elements
-- l_Elements(3) := 3;
-- return the cursor into a bind variable (to be used in the host environment)
:p_Cursor := pivot_it(l_Elements);
end;
この関数から返されたカーソルをどのように使用するかは、使用している環境によって異なります。SQL/Plus では、カーソルを印刷するだけでよく、ほとんどのプログラミング言語の Oracle バインディングはすぐに使用できます。
注意: このコードは、提供されたデータに対して機能しますが、基本的なエラー チェックさえ行われていません。動的 SQL は常に SQL インジェクション攻撃のターゲットになる可能性があるため、これは特に重要です。