sql >> Database >  >> RDS >> Oracle

Transponeer queryresultaat in Oracle 11g

Je bent dichtbij - wat je wilt is een combinatie van UNPIVOT en 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

Deze vraag

  • converteert de kolommen lezen1, lezen2, lezen3 in afzonderlijke rijen (de naam gaat in reading_name , de waarde in reading_value ); dit geeft ons één rij per (element,reading_name)
  • converteert de rijen 1, 2*, 3 (de waarden voor element ) in kolommen '1', '2', '3'; dit geeft ons één rij per reading_name

UPDATE

Als de lijst met elementen pas tijdens runtime bekend is (bijvoorbeeld omdat de gebruiker de mogelijkheid heeft om ze te selecteren), hebt u een meer dynamische aanpak nodig. Hier is een oplossing die dynamisch een SQL-instructie maakt voor de gegeven lijst met elementen en een sys_refcursor gebruikt voor de resultatenset.

-- 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;

Hoe u de cursor gebruikt die door deze functie wordt geretourneerd, hangt af van de omgeving die u gebruikt - in SQL/Plus kunt u deze gewoon afdrukken, en de Oracle-bindingen van de meeste programmeertalen ondersteunen het out-of-the-box.

WAARSCHUWING: Hoewel deze code werkt voor de verstrekte gegevens, ontbreekt het zelfs aan elementaire foutcontrole. Dit is vooral belangrijk omdat dynamische SQL altijd een mogelijk doelwit is voor SQL-injectieaanvallen.




  1. Vind punt in polygoon PHP

  2. Wijzig datumnotatie in mySql-databasetabel

  3. Met PyMySQL kan ik geen verbinding maken met RDS

  4. Zoek in meerdere tabellen naar dezelfde waarde