Anda sudah dekat - yang Anda inginkan adalah kombinasi UNPIVOT
dan 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
Kueri ini
- mengonversi kolom membaca1, membaca2, membaca3 menjadi baris yang terpisah (namanya masuk ke reading_name , nilai menjadi reading_value ); ini memberi kita satu baris per (elemen,reading_name)
- mengonversi baris 1, 2*, 3 (nilai untuk elemen ) ke dalam kolom '1', '2', '3'; ini memberi kita satu baris per reading_name
PERBARUI
Jika daftar elemen tidak diketahui sampai waktu berjalan (misalnya karena pengguna memiliki opsi untuk memilihnya), Anda memerlukan pendekatan yang lebih dinamis. Berikut adalah salah satu solusi yang secara dinamis membuat pernyataan SQL untuk daftar elemen yang diberikan dan menggunakan sys_refcursor
untuk kumpulan hasil.
-- 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;
Cara Anda menggunakan kursor yang dikembalikan dari fungsi ini bergantung pada lingkungan yang Anda gunakan - dalam SQL/Plus Anda dapat mencetaknya, dan sebagian besar binding Oracle bahasa pemrograman mendukungnya secara langsung.
PERINGATAN: Meskipun kode ini berfungsi untuk data yang diberikan, kode ini bahkan tidak memiliki pemeriksaan kesalahan dasar. Ini sangat penting karena SQL dinamis selalu menjadi target serangan injeksi SQL.