sql >> Database teknologi >  >> RDS >> Oracle

Transponer forespørgselsresultat i Oracle 11g

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.




  1. Sådan hentes billede fra databasen i c#

  2. Fremstil et 'DataSource'-objekt til Postgres JDBC, programmatisk

  3. Tjek længden af ​​kolonnen i XMLTable

  4. Hvordan sletter jeg et fast antal rækker med sortering i PostgreSQL?