sql >> Databáze >  >> RDS >> Oracle

Transponujte výsledek dotazu v Oracle 11g

Jste blízko – to, co chcete, je kombinace UNPIVOT a 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

Tento dotaz

  • převede sloupce čtení1, čtení2, čtení3 do samostatných řádků (název přejde do název_čtení , hodnotu do reading_value ); to nám dává jeden řádek na (element,reading_name)
  • převede řádky 1, 2*, 3 (hodnoty pro element ) do sloupců '1', '2', '3'; to nám dává jeden řádek na read_name

AKTUALIZACE

Pokud není seznam prvků znám až do doby spuštění (např. protože uživatel má možnost je vybrat), potřebujete dynamičtější přístup. Zde je jedno řešení, které dynamicky vytváří SQL příkaz pro daný seznam prvků a používá sys_refcursor pro sadu výsledků.

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

To, jak použijete kurzor vrácený touto funkcí, závisí na prostředí, které používáte – v SQL/Plus jej můžete pouze vytisknout a vazby Oracle většiny programovacích jazyků jej přímo podporují.

UPOZORNĚNÍ: I když tento kód funguje pro poskytnutá data, postrádá dokonce základní kontrolu chyb. To je zvláště důležité, protože dynamický SQL je vždy možným cílem útoků SQL injection.




  1. Jak Java pro OS X 2013-004 ovlivňuje (přerušuje) aplikace Swing?

  2. Úprava úlohy SQL Server Agent (T-SQL)

  3. SQL Server:Databáze se zasekla ve stavu Obnovování

  4. Rozdíl mezi TRUNCATE a DELETE?