Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Transponieren Sie das Abfrageergebnis in Oracle 11g

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.