Sie sind nah dran – was Sie wollen, ist eine Kombination aus UNPIVOT
und 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
Diese Abfrage
- konvertiert die Spalten Messwert1, Messwert2, Messwert3 in separate Zeilen (der Name kommt in reading_name , den Wert in reading_value ); das gibt uns eine Zeile pro (element,reading_name)
- konvertiert die Zeilen 1, 2*, 3 (die Werte für element ) in die Spalten „1“, „2“, „3“; das gibt uns eine Zeile pro Reading_name
AKTUALISIEREN
Wenn die Liste der Elemente bis zur Laufzeit nicht bekannt ist (z. B. weil der Benutzer die Möglichkeit hat, sie auszuwählen), benötigen Sie einen dynamischeren Ansatz. Hier ist eine Lösung, die dynamisch eine SQL-Anweisung für die angegebene Liste von Elementen erstellt und einen sys_refcursor
verwendet für die Ergebnismenge.
-- 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;
Wie Sie den von dieser Funktion zurückgegebenen Cursor verwenden, hängt von der verwendeten Umgebung ab - in SQL/Plus können Sie ihn einfach drucken, und die Oracle-Bindungen der meisten Programmiersprachen unterstützen ihn standardmäßig.
ACHTUNG: Während dieser Code für die bereitgestellten Daten funktioniert, fehlt ihm sogar eine grundlegende Fehlerprüfung. Dies ist besonders wichtig, da dynamisches SQL immer ein mögliches Ziel für SQL-Injection-Angriffe ist.