Du er tæt på - det, du ønsker, er en kombination af UNPIVOT
og 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
Denne forespørgsel
- konverterer kolonnerne læsning1, læsning2, læsning3 i separate rækker (navnet går ind i læsenavn , værdien til læseværdi ); dette giver os én række pr. (element, læsenavn)
- konverterer rækkerne 1, 2*, 3 (værdierne for element ) i kolonnerne '1', '2', '3'; dette giver os én række pr. læsenavn
OPDATERING
Hvis listen over elementer ikke er kendt før køretid (f.eks. fordi brugeren har mulighed for at vælge dem), har du brug for en mere dynamisk tilgang. Her er en løsning, der dynamisk opretter en SQL-sætning for den givne liste over elementer og bruger en sys_refcursor
for resultatsættet.
-- 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;
Hvordan du bruger markøren, der returneres fra denne funktion, afhænger af det miljø, du bruger - i SQL/Plus kan du bare udskrive det, og de fleste programmeringssprogs Oracle-bindinger understøtter det ud af boksen.
ADVARSEL: Selvom denne kode fungerer for de angivne data, mangler den selv grundlæggende fejlkontrol. Dette er især vigtigt, fordi dynamisk SQL altid er et muligt mål for SQL-injektionsangreb.