Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Transpozycja wyników zapytania w Oracle 11g

Jesteś blisko — chcesz mieć kombinację UNPIVOT i 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

To zapytanie

  • konwertuje kolumny czytanie1, czytanie2, czytanie3 w osobnych wierszach (nazwa przechodzi w reading_name , wartość do reading_value ); to daje nam jeden wiersz na (element,reading_name)
  • konwertuje wiersze 1, 2*, 3 (wartości dla elementu ) w kolumnach „1”, „2”, „3”; to daje nam jeden wiersz na read_name

AKTUALIZUJ

Jeśli lista elementów nie jest znana do czasu uruchomienia (np. dlatego, że użytkownik ma możliwość ich wyboru), potrzebujesz bardziej dynamicznego podejścia. Oto jedno rozwiązanie, które dynamicznie tworzy instrukcję SQL dla podanej listy elementów i używa sys_refcursor dla zestawu wyników.

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

Sposób użycia kursora zwróconego przez tę funkcję zależy od używanego środowiska — w SQL/Plus można go po prostu wydrukować, a powiązania Oracle w większości języków programowania obsługują go od razu po zainstalowaniu.

OSTRZEŻENIE: Chociaż ten kod działa dla dostarczonych danych, brakuje w nim nawet podstawowego sprawdzania błędów. Jest to szczególnie ważne, ponieważ dynamiczny SQL jest zawsze możliwym celem ataków typu SQL injection.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak prawidłowo używać AddBatch/withBatch do zbiorczego wstawiania wartości tagu xml do tabeli bazy danych?

  2. Literał nie pasuje do ciągu formatu dla Oracle SQL to_date w kolumnie ciągu

  3. Wartość wstawiona do tabeli w oracle nie została zapisana?

  4. Zarządzanie obsługą błędów podczas uruchamiania sqlplus ze skryptów powłoki

  5. Jak mogę zwrócić ciąg CSV z typu tabeli PL/SQL w Oracle?